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 <caol...@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; } }
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits