[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