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.kagan...@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 <c...@libreoffice.org> Reviewed-by: Mike Kaganski <mike.kagan...@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 ) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits