[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