[Libreoffice-commits] core.git: vcl/qa vcl/source
Mike Kaganski
mike.kaganski at collabora.com
Tue Dec 27 00:22:54 UTC 2016
vcl/qa/cppunit/wmf/data/tdf39894.emf |binary
vcl/qa/cppunit/wmf/data/tdf39894.wmf |binary
vcl/qa/cppunit/wmf/wmfimporttest.cxx | 23 ++++++++++++++
vcl/source/filter/wmf/enhwmf.cxx | 15 +++++----
vcl/source/filter/wmf/winmtf.cxx | 18 +++++------
vcl/source/filter/wmf/winwmf.cxx | 54 +++++++++++++++++++----------------
6 files changed, 71 insertions(+), 39 deletions(-)
New commits:
commit 3fe6703ac30177a939839a70e650eb344c8a9abc
Author: Mike Kaganski <mike.kaganski at collabora.com>
Date: Mon Dec 26 22:04:23 2016 +0300
tdf#39894: Metafile: use distance from last char cell to next
The optional Dx array of WMF's META_EXTTEXTOUT (and its EMF
counterpart) define not only spacing between char cells of this
record, but also of spacing to first char cell of next text
(if TA_UPDATECP is set). Additionally, both WMF and EMF EXTTEXTOUT
records define not only X spacing, but also Y (if ETO_PDY is set
in its options).
Unit test is included.
Change-Id: I45ed872210c81b3050ba65d68145b64861bfec22
Reviewed-on: https://gerrit.libreoffice.org/32436
Tested-by: Jenkins <ci at libreoffice.org>
Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
diff --git a/vcl/qa/cppunit/wmf/data/tdf39894.emf b/vcl/qa/cppunit/wmf/data/tdf39894.emf
new file mode 100644
index 0000000..c9d5b95
Binary files /dev/null and b/vcl/qa/cppunit/wmf/data/tdf39894.emf differ
diff --git a/vcl/qa/cppunit/wmf/data/tdf39894.wmf b/vcl/qa/cppunit/wmf/data/tdf39894.wmf
new file mode 100644
index 0000000..32e41de
Binary files /dev/null and b/vcl/qa/cppunit/wmf/data/tdf39894.wmf differ
diff --git a/vcl/qa/cppunit/wmf/wmfimporttest.cxx b/vcl/qa/cppunit/wmf/wmfimporttest.cxx
index 7698300..9315c1e 100644
--- a/vcl/qa/cppunit/wmf/wmfimporttest.cxx
+++ b/vcl/qa/cppunit/wmf/wmfimporttest.cxx
@@ -59,6 +59,7 @@ public:
void testWorldTransformFontSize();
void testTdf93750();
void testTdf99402();
+ void testTdf39894();
CPPUNIT_TEST_SUITE(WmfTest);
CPPUNIT_TEST(globalSetUp);
@@ -69,6 +70,7 @@ public:
CPPUNIT_TEST(testWorldTransformFontSize);
CPPUNIT_TEST(testTdf93750);
CPPUNIT_TEST(testTdf99402);
+ CPPUNIT_TEST(testTdf39894);
CPPUNIT_TEST_SUITE_END();
};
@@ -266,6 +268,27 @@ void WmfTest::testTdf99402()
CPPUNIT_ASSERT_EQUAL(RTL_TEXTENCODING_SYMBOL, fontStyle.aFont.GetCharSet());
}
+void WmfTest::testTdf39894()
+{
+ OUString files[] = { "tdf39894.wmf", "tdf39894.emf" };
+ for (const auto& file: files)
+ {
+ SvFileStream aFileStream(getFullUrl(file), StreamMode::READ);
+ GDIMetaFile aGDIMetaFile;
+ ReadWindowMetafile(aFileStream, aGDIMetaFile);
+
+ MetafileXmlDump dumper;
+ xmlDocPtr pDoc = dumper.dumpAndParse(aGDIMetaFile);
+
+ CPPUNIT_ASSERT(pDoc);
+
+ // The x position of the second text must take into account
+ // the previous text's last Dx (previously was ~300)
+ auto x = getXPath(pDoc, "/metafile/push[2]/textarray[2]", "x");
+ CPPUNIT_ASSERT_MESSAGE(file.toUtf8().getStr(), x.toInt32() > 2700);
+ }
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(WmfTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/vcl/source/filter/wmf/enhwmf.cxx b/vcl/source/filter/wmf/enhwmf.cxx
index a8118a2..f5ee19a 100644
--- a/vcl/source/filter/wmf/enhwmf.cxx
+++ b/vcl/source/filter/wmf/enhwmf.cxx
@@ -1568,17 +1568,20 @@ bool EnhWMFReader::ReadEnhWMF()
bool bOffStringSane = nOffString <= nEndPos - nCurPos;
if (bLenSane && bOffStringSane)
{
- if ( offDx && (( nCurPos + offDx + nLen * 4 ) <= nNextPos ) )
+ sal_Int32 nDxSize = nLen * ((nOptions & ETO_PDY) ? 8 : 4);
+ if ( offDx && (( nCurPos + offDx + nDxSize ) <= nNextPos ) && nNextPos <= nEndPos )
{
pWMF->Seek( nCurPos + offDx );
- if ( ( nLen * sizeof(sal_uInt32) ) <= ( nEndPos - pWMF->Tell() ) )
+ aDX.resize(nLen);
+ for (sal_Int32 i = 0; i < nLen; ++i)
{
- aDX.resize(nLen);
- for (sal_Int32 i = 0; i < nLen; ++i)
+ sal_Int32 val(0);
+ pWMF->ReadInt32(val);
+ aDX[i] = val;
+ if (nOptions & ETO_PDY)
{
- sal_Int32 val(0);
pWMF->ReadInt32(val);
- aDX[i] = val;
+ // TODO: Use Dy value
}
}
}
diff --git a/vcl/source/filter/wmf/winmtf.cxx b/vcl/source/filter/wmf/winmtf.cxx
index c318956..3165cee 100644
--- a/vcl/source/filter/wmf/winmtf.cxx
+++ b/vcl/source/filter/wmf/winmtf.cxx
@@ -1363,14 +1363,12 @@ void WinMtfOutput::DrawText( Point& rPosition, OUString& rText, long* pDXArry, b
for (i = 0; i < nLen; i++ )
{
- if (i > 0)
- {
- // #i121382# Map DXArray using WorldTransform
- const Size aSize(ImplMap(Size(nSum, 0)));
- const basegfx::B2DVector aVector(aSize.Width(), aSize.Height());
- pDXArry[i - 1] = basegfx::fround(aVector.getLength());
- }
nSum += pDXArry[i];
+
+ // #i121382# Map DXArray using WorldTransform
+ const Size aSize(ImplMap(Size(nSum, 0)));
+ const basegfx::B2DVector aVector(aSize.Width(), aSize.Height());
+ pDXArry[i] = basegfx::fround(aVector.getLength());
}
}
if ( mnLatestTextLayoutMode != mnTextLayoutMode )
@@ -1457,7 +1455,7 @@ void WinMtfOutput::DrawText( Point& rPosition, OUString& rText, long* pDXArry, b
// #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
SolarMutexGuard aGuard;
ScopedVclPtrInstance< VirtualDevice > pVDev;
- sal_Int32 nTextWidth;
+ sal_Int32 nTextWidth, nActPosDeltaX = 0;
pVDev->SetMapMode( MapMode( MapUnit::Map100thMM ) );
pVDev->SetFont( maFont );
if( pDXArry )
@@ -1466,6 +1464,8 @@ void WinMtfOutput::DrawText( Point& rPosition, OUString& rText, long* pDXArry, b
nTextWidth = pVDev->GetTextWidth( OUString(rText[ nLen - 1 ]) );
if( nLen > 1 )
nTextWidth += pDXArry[ nLen - 2 ];
+ // tdf#39894: We should consider the distance to next character cell origin
+ nActPosDeltaX = pDXArry[ nLen - 1 ];
}
else
nTextWidth = pVDev->GetTextWidth( rText );
@@ -1481,7 +1481,7 @@ void WinMtfOutput::DrawText( Point& rPosition, OUString& rText, long* pDXArry, b
}
if( mnTextAlign & TA_UPDATECP )
- maActPos.X() = rPosition.X() + nTextWidth;
+ maActPos.X() = rPosition.X() + (pDXArry ? nActPosDeltaX : nTextWidth);
}
if ( bChangeFont || ( maLatestFont != aTmp ) )
{
diff --git a/vcl/source/filter/wmf/winwmf.cxx b/vcl/source/filter/wmf/winwmf.cxx
index 72a726a..7fd1fc7 100644
--- a/vcl/source/filter/wmf/winwmf.cxx
+++ b/vcl/source/filter/wmf/winwmf.cxx
@@ -519,19 +519,13 @@ void WMFReader::ReadRecordParams( sal_uInt16 nFunc )
case W_META_EXTTEXTOUT:
{
- sal_uInt16 nLen = 0, nOptions = 0;
- sal_Int32 nRecordPos, nRecordSize = 0, nOriginalTextLen, nNewTextLen;
- Point aPosition;
- Rectangle aRect;
- std::unique_ptr<long[]> pDXAry;
-
pWMF->SeekRel(-6);
- nRecordPos = pWMF->Tell();
+ sal_Int32 nRecordPos = pWMF->Tell(), nRecordSize = 0;
pWMF->ReadInt32( nRecordSize );
pWMF->SeekRel(2);
- aPosition = ReadYX();
- pWMF->ReadUInt16( nLen );
- pWMF->ReadUInt16( nOptions );
+ Point aPosition = ReadYX();
+ sal_uInt16 nLen = 0, nOptions = 0;
+ pWMF->ReadUInt16( nLen ).ReadUInt16( nOptions );
ComplexTextLayoutFlags nTextLayoutMode = ComplexTextLayoutFlags::Default;
if ( nOptions & ETO_RTLREADING )
@@ -542,7 +536,8 @@ void WMFReader::ReadRecordParams( sal_uInt16 nFunc )
// output only makes sense if the text contains characters
if( nLen )
{
- nOriginalTextLen = nLen;
+ sal_Int32 nOriginalTextLen = nLen;
+ Rectangle aRect;
if( nOptions & ETO_CLIPPED )
{
const Point aPt1( ReadPoint() );
@@ -552,11 +547,11 @@ void WMFReader::ReadRecordParams( sal_uInt16 nFunc )
std::unique_ptr<char[]> pChar(new char[ ( nOriginalTextLen + 1 ) &~ 1 ]);
pWMF->ReadBytes(pChar.get(), (nOriginalTextLen + 1) &~ 1);
OUString aText( pChar.get(), (sal_uInt16)nOriginalTextLen, pOut->GetCharSet() );// after this conversion the text may contain
- nNewTextLen = aText.getLength(); // less character (japanese version), so the
- pChar.reset(); // dxAry will not fit
-
+ sal_Int32 nNewTextLen = aText.getLength(); // less character (japanese version), so the
+ // dxAry will not fit
if ( nNewTextLen )
{
+ std::unique_ptr<long[]> pDXAry;
sal_uInt32 nMaxStreamPos = nRecordPos + ( nRecordSize << 1 );
sal_Int32 nDxArySize = nMaxStreamPos - pWMF->Tell();
sal_Int32 nDxAryEntries = nDxArySize >> 1;
@@ -564,30 +559,41 @@ void WMFReader::ReadRecordParams( sal_uInt16 nFunc )
if ( ( ( nDxAryEntries % nOriginalTextLen ) == 0 ) && ( nNewTextLen <= nOriginalTextLen ) )
{
- sal_Int16 nDx = 0, nDxTmp = 0;
- sal_uInt16 i; //needed just outside the for
+ sal_uInt16 i; // needed just outside the for
pDXAry.reset(new long[ nNewTextLen ]);
for (i = 0; i < nNewTextLen; i++ )
{
if ( pWMF->Tell() >= nMaxStreamPos )
break;
- pWMF->ReadInt16( nDx );
+ sal_Int32 nDxCount = 1;
if ( nNewTextLen != nOriginalTextLen )
{
sal_Unicode nUniChar = aText[i];
OString aTmp(&nUniChar, 1, pOut->GetCharSet());
if ( aTmp.getLength() > 1 )
{
- sal_Int32 nDxCount = aTmp.getLength() - 1;
- if ( ( ( nDxCount * 2 ) + pWMF->Tell() ) > nMaxStreamPos )
+ nDxCount = aTmp.getLength();
+ }
+ }
+
+ sal_Int16 nDx = 0;
+ while ( nDxCount-- )
+ {
+ if ( ( pWMF->Tell() + 2 ) > nMaxStreamPos )
+ break;
+ sal_Int16 nDxTmp = 0;
+ pWMF->ReadInt16(nDxTmp);
+ nDx += nDxTmp;
+ if ( nOptions & ETO_PDY )
+ {
+ if ( ( pWMF->Tell() + 2 ) > nMaxStreamPos )
break;
- while ( nDxCount-- )
- {
- pWMF->ReadInt16( nDxTmp );
- nDx = nDx + nDxTmp;
- }
+ sal_Int16 nDyTmp = 0;
+ pWMF->ReadInt16(nDyTmp);
+ // TODO: use Dy offset
}
}
+
pDXAry[ i ] = nDx;
}
if ( i == nNewTextLen )
More information about the Libreoffice-commits
mailing list