[Libreoffice-commits] core.git: filter/source include/filter oox/source sw/qa sw/source

Caolán McNamara caolanm at redhat.com
Wed Jun 10 09:53:29 PDT 2015


 filter/source/msfilter/escherex.cxx       |   47 ++++++++++-------
 include/filter/msfilter/escherex.hxx      |   12 ++++
 oox/source/export/vmlexport.cxx           |   81 +++++++++++++++++-------------
 sw/qa/extras/ooxmlexport/ooxmlexport5.cxx |   10 +--
 sw/source/filter/ww8/rtfsdrexport.cxx     |   79 +++++++++++++++++------------
 5 files changed, 136 insertions(+), 93 deletions(-)

New commits:
commit b04e1e79e64cb7bb3106fd08a019c27b09bdd5c6
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Jun 10 15:34:44 2015 +0100

    Prop_pSegmentInfo is totally misunderstood apparently
    
    digging into the crash on export of kde216114-1.odt
    reveals various horrors
    
    Change-Id: I0d24fe303d561a00a08098b306d10fd8273af928

diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx
index 93b2d95..1e298dc 100644
--- a/filter/source/msfilter/escherex.cxx
+++ b/filter/source/msfilter/escherex.cxx
@@ -3253,85 +3253,92 @@ void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeT
                                                .WriteUInt16( nElementSize );
                                             for ( j = 0; j < nElements; j++ )
                                             {
+                                                // The segment type is stored in the upper 3 bits
+                                                // and segment count is stored in the lower 13
+                                                // bits.
+                                                //
+                                                // If the segment type is msopathEscape, the lower 13 bits
+                                                // are divided in a 5 bit escape code and 8 bit
+                                                // vertex count (not segment count!)
                                                 sal_uInt16 nVal = (sal_uInt16)aSegments[ j ].Count;
                                                 switch( aSegments[ j ].Command )
                                                 {
-                                                    case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN :
-                                                    case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO : break;
-                                                    case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
-                                                    {
-                                                        nVal = 0x4000;
-                                                    }
-                                                    break;
+                                                    case css::drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN :
+                                                    case css::drawing::EnhancedCustomShapeSegmentCommand::LINETO :
+                                                        break;
+                                                    case css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
+                                                        nVal = (msopathMoveTo << 13);
+                                                        break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
                                                     {
-                                                        nVal |= 0x2000;
+                                                        nVal |= (msopathCurveTo << 13);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
                                                     {
-                                                        nVal = 0x6001;
+                                                        nVal = 1;
+                                                        nVal |= (msopathClose << 13);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
                                                     {
-                                                        nVal = 0x8000;
+                                                        nVal = (msopathEnd << 13);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOFILL :
                                                     {
-                                                        nVal = 0xaa00;
+                                                        nVal = (msopathEscape << 13) | (5 << 8);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE :
                                                     {
-                                                        nVal = 0xab00;
+                                                        nVal = (msopathEscape << 13) | (11 << 8);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
                                                     {
                                                         nVal *= 3;
-                                                        nVal |= 0xa100;
+                                                        nVal |= (msopathEscape << 13) | (1 << 8);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
                                                     {
                                                         nVal *= 3;
-                                                        nVal |= 0xa200;
+                                                        nVal |= (msopathEscape << 13) | (2 << 8);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
                                                     {
                                                         nVal <<= 2;
-                                                        nVal |= 0xa300;
+                                                        nVal |= (msopathEscape << 13) | (3 << 8);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARC :
                                                     {
                                                         nVal <<= 2;
-                                                        nVal |= 0xa400;
+                                                        nVal |= (msopathEscape << 13) | (4 << 8);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
                                                     {
                                                         nVal <<= 2;
-                                                        nVal |= 0xa500;
+                                                        nVal |= (msopathEscape << 13) | (5 << 8);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
                                                     {
                                                         nVal <<= 2;
-                                                        nVal |= 0xa600;
+                                                        nVal |= (msopathEscape << 13) | (6 << 8);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
                                                     {
-                                                        nVal |= 0xa700;
+                                                        nVal |= (msopathEscape << 13) | (7 << 8);
                                                     }
                                                     break;
                                                     case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
                                                     {
-                                                        nVal |= 0xa800;
+                                                        nVal |= (msopathEscape << 13) | (8 << 8);
                                                     }
                                                     break;
                                                 }
diff --git a/include/filter/msfilter/escherex.hxx b/include/filter/msfilter/escherex.hxx
index 8c1fbbe..a9f0fc8 100644
--- a/include/filter/msfilter/escherex.hxx
+++ b/include/filter/msfilter/escherex.hxx
@@ -424,6 +424,18 @@ enum ESCHER_LineCap
     ESCHER_LineEndCapFlat     // Line ends at end point
 };
 
+enum MSOPATHTYPE
+{
+    msopathLineTo,        // Draw a straight line (one point)
+    msopathCurveTo,       // Draw a cubic Bezier curve (three points)
+    msopathMoveTo,        // Move to a new point (one point)
+    msopathClose,         // Close a sub - path (no points)
+    msopathEnd,           // End a path (no points)
+    msopathEscape,        // Escape code
+    msopathClientEscape,  // Escape code interpreted by the client
+    msopathInvalid        // Invalid - should never be found
+};
+
 // Shape Properties
 // 1pt = 12700 EMU (English Metric Units)
 // 1pt = 20 Twip = 20/1440" = 1/72"
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 9e8e6d2..7161a2f 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -474,27 +474,56 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const Rectangle& rRect
                         for ( ; nSegments; --nSegments )
                         {
                             sal_uInt16 nSeg = impl_GetUInt16( pSegmentIt );
-                            switch ( nSeg )
+
+                            // The segment type is stored in the upper 3 bits
+                            // and segment count is stored in the lower 13
+                            // bits.
+                            unsigned char nSegmentType = (nSeg & 0xE000) >> 13;
+                            unsigned short nSegmentCount = nSeg & 0x03FF;
+
+                            switch (nSegmentType)
                             {
-                                case 0x4000: // moveto
+                                case msopathMoveTo:
+                                {
+                                    sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize );
+                                    sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize );
+                                    if (nX >= 0 && nY >= 0 )
+                                        aPath.append( "m" ).append( nX ).append( "," ).append( nY );
+                                    break;
+                                }
+                                case msopathClientEscape:
+                                    break;
+                                case msopathEscape:
+                                {
+                                    // If the segment type is msopathEscape, the lower 13 bits are
+                                    // divided in a 5 bit escape code and 8 bit
+                                    // vertex count (not segment count!)
+                                    unsigned char nEscapeCode = (nSegmentCount & 0x1F00) >> 8;
+                                    unsigned char nVertexCount = nSegmentCount & 0x00FF;
+                                    pVerticesIt += nVertexCount;
+
+                                    switch (nEscapeCode)
                                     {
-                                        sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize );
-                                        sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize );
-                                        if (nX >= 0 && nY >= 0 )
-                                            aPath.append( "m" ).append( nX ).append( "," ).append( nY );
+                                        case 0xa: // nofill
+                                            aPath.append( "nf" );
+                                            break;
+                                        case 0xb: // nostroke
+                                            aPath.append( "ns" );
+                                            break;
                                     }
+
                                     break;
-                                case 0xb300:
-                                case 0xac00:
-                                    break;
-                                case 0x0001: // lineto
+                                }
+                                case msopathLineTo:
+                                    for (unsigned short i = 0; i < nSegmentCount; ++i)
                                     {
                                         sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize );
                                         sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize );
                                         aPath.append( "l" ).append( nX ).append( "," ).append( nY );
                                     }
                                     break;
-                                case 0x2001: // curveto
+                                case msopathCurveTo:
+                                    for (unsigned short i = 0; i < nSegmentCount; ++i)
                                     {
                                         sal_Int32 nX1 = impl_GetPointComponent( pVerticesIt, nPointSize );
                                         sal_Int32 nY1 = impl_GetPointComponent( pVerticesIt, nPointSize );
@@ -507,35 +536,17 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const Rectangle& rRect
                                             .append( nX3 ).append( "," ).append( nY3 );
                                     }
                                     break;
-                                case 0xaa00: // nofill
-                                    aPath.append( "nf" );
-                                    break;
-                                case 0xab00: // nostroke
-                                    aPath.append( "ns" );
-                                    break;
-                                case 0x6001: // close
+                                case msopathClose:
                                     aPath.append( "x" );
                                     break;
-                                case 0x8000: // end
+                                case msopathEnd:
                                     aPath.append( "e" );
                                     break;
                                 default:
-                                    // See EscherPropertyContainer::CreateCustomShapeProperties, by default nSeg is simply the number of points.
-                                    // FIXME: we miss out a significant amount of complexity from
-                                    // the above method here, and do some rather odd things to match.
-                                    int nElems = !nPointSize ? 0 : aVertices.nPropSize / (nPointSize * 2);
-                                    if (nSeg > nElems)
-                                    {
-                                        SAL_WARN("oox", "Busted escher export " << nSeg << "vs . " << nElems << " truncating point stream");
-                                        nSeg = nElems;
-                                    }
-                                    for (int i = 0; i < nSeg; ++i)
-                                    {
-                                        sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nPointSize);
-                                        sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nPointSize);
-                                        if (nX >= 0 && nY >= 0 )
-                                            aPath.append("l").append(nX).append(",").append(nY);
-                                    }
+                                    SAL_WARN("oox", "Totally b0rked\n");
+                                    break;
+                                case msopathInvalid:
+                                    SAL_WARN("oox", "Invalid - should never be found");
                                     break;
                             }
                         }
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
index aea445e..14be93e 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
@@ -837,11 +837,11 @@ DECLARE_OOXMLEXPORT_TEST(testKDE302504, "kde302504-1.odt")
         assertXPath(pXmlDoc, "//v:shape", "ID", "KoPathShape");
 }
 
-//DECLARE_OOXMLEXPORT_TEST(testKDE216114, "kde216114-1.odt")
-//{
-//    if (xmlDocPtr pXmlDoc = parseExport("word/document.xml"))
-//        assertXPath(pXmlDoc, "//w:pict", 1);
-//}
+DECLARE_OOXMLEXPORT_TEST(testKDE216114, "kde216114-1.odt")
+{
+    if (xmlDocPtr pXmlDoc = parseExport("word/document.xml"))
+        assertXPath(pXmlDoc, "//w:pict", 1);
+}
 
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/filter/ww8/rtfsdrexport.cxx b/sw/source/filter/ww8/rtfsdrexport.cxx
index d6df7f7..5d01fbc 100644
--- a/sw/source/filter/ww8/rtfsdrexport.cxx
+++ b/sw/source/filter/ww8/rtfsdrexport.cxx
@@ -278,48 +278,61 @@ void RtfSdrExport::Commit(EscherPropertyContainer& rProps, const Rectangle& rRec
                 for (; nSegments; --nSegments)
                 {
                     sal_uInt16 nSeg = impl_GetUInt16(pSegmentIt);
+
+                    // The segment type is stored in the upper 3 bits
+                    // and segment count is stored in the lower 13
+                    // bits.
+                    unsigned char nSegmentType = (nSeg & 0xE000) >> 13;
+                    unsigned short nSegmentCount = nSeg & 0x03FF;
+
                     aSegmentInfo.append(';').append((sal_Int32)nSeg);
-                    switch (nSeg)
-                    {
-                    case 0x0001: // lineto
-                    case 0x4000: // moveto
-                    {
-                        sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
-                        sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
-                        aVerticies.append(";(").append(nX).append(",").append(nY).append(")");
-                        nVertices ++;
-                    }
-                    break;
-                    case 0x2001: // curveto
+                    switch (nSegmentType)
                     {
-                        for (int i = 0; i < 3; i++)
+                        case msopathLineTo:
+                            for (unsigned short i = 0; i < nSegmentCount; ++i)
+                            {
+                                sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
+                                sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
+                                aVerticies.append(";(").append(nX).append(",").append(nY).append(")");
+                                nVertices ++;
+                            }
+                            break;
+                        case msopathMoveTo:
                         {
                             sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
                             sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
                             aVerticies.append(";(").append(nX).append(",").append(nY).append(")");
-                            nVertices ++;
+                            nVertices++;
+                            break;
                         }
-                    }
-                    break;
-                    case 0xb300:
-                    case 0xac00:
-                    case 0xaa00: // nofill
-                    case 0xab00: // nostroke
-                    case 0x6001: // close
-                    case 0x8000: // end
-                        break;
-                    default:
-                        // See EscherPropertyContainer::CreateCustomShapeProperties, by default nSeg is simply the number of points.
-                        for (int i = 0; i < nSeg; ++i)
+                        case msopathCurveTo:
+                            for (unsigned short j = 0; j < nSegmentCount; ++j)
+                            {
+                                for (int i = 0; i < 3; i++)
+                                {
+                                    sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
+                                    sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
+                                    aVerticies.append(";(").append(nX).append(",").append(nY).append(")");
+                                    nVertices ++;
+                                }
+                            }
+                            break;
+                        case msopathEscape:
                         {
-                            if (nVerticesPos >= aVertices.nPropSize)
-                                break;
-                            sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
-                            sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
-                            aVerticies.append(";(").append(nX).append(",").append(nY).append(")");
-                            ++nVertices;
+                            // If the segment type is msopathEscape, the lower 13 bits are
+                            // divided in a 5 bit escape code and 8 bit
+                            // vertex count (not segment count!)
+                            unsigned char nVertexCount = nSegmentCount & 0x00FF;
+                            nVerticesPos += nVertexCount;
+                            break;
                         }
-                        break;
+                        case msopathClientEscape:
+                        case msopathClose:
+                        case msopathEnd:
+                            break;
+                        default:
+                            SAL_WARN("oox", "Totally b0rked\n");
+                            break;
                     }
                 }
 


More information about the Libreoffice-commits mailing list