You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by pe...@apache.org on 2026/07/07 04:01:03 UTC

(openoffice) 01/11: filter: idxf: chunk oversized LWPOLYLINE instead of truncating the count

This is an automated email from the ASF dual-hosted git repository.

leginee pushed a commit to branch bugfix-dxf-filter
in repository https://gitbox.apache.org/repos/asf/openoffice.git

commit 999d0e5d3c8f710c68c553b185539e922d0809c9
Author: Peter Kovacs <pe...@apache.org>
AuthorDate: Thu Jul 2 22:15:55 2026 +0200

    filter: idxf: chunk oversized LWPOLYLINE instead of truncating the count
    
    A DXF LWPOLYLINE vertex count (group code 90) is 32-bit, but tools::Polygon
    is indexed by sal_uInt16. Render polylines with more than 65535 points as
    consecutive Polygon segments that overlap by one point, walking the source
    array with the full 32-bit index, so the whole line is drawn without
    narrowing it to 16 bits.
    
    Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
    (cherry picked from commit 2f0de83e3857a766280165977d6304354eb43806)
    (cherry picked from commit ac9bccefb1d87a770f60d12a2e6523cc8ef496a9)
---
 main/filter/source/graphicfilter/idxf/dxf2mtf.cxx | 65 +++++++++++++++++------
 1 file changed, 48 insertions(+), 17 deletions(-)

diff --git a/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx b/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx
index 7f2706117d..3ee67f6797 100644
--- a/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx
+++ b/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx
@@ -586,24 +586,55 @@ void DXF2GDIMetaFile::DrawPolyLineEntity(const DXFPolyLineEntity & rE, const DXF
 
 void DXF2GDIMetaFile::DrawLWPolyLineEntity(const DXFLWPolyLineEntity & rE, const DXFTransform & rTransform )
 {
-	sal_Int32 i, nPolySize = rE.nCount;
-	if ( nPolySize && rE.pP )
+	const sal_Int32 nPolySize = rE.nCount;
+	if ( nPolySize <= 0 || rE.pP == NULL )
+		return;
+
+	double fW = rE.fConstantWidth;
+	if ( !SetLineAttribute( rE, rTransform.TransLineWidth( fW ) ) )
+		return;
+
+	const sal_Bool bClosed = ( rE.nFlags & 1 ) != 0;
+
+	if ( nPolySize <= 0xFFFF )
 	{
-		Polygon aPoly( (sal_uInt16)nPolySize);
-		for ( i = 0; i < nPolySize; i++ )
-		{
-			rTransform.Transform( rE.pP[ (sal_uInt16)i ], aPoly[ (sal_uInt16)i ] );
-		}
-		double fW = rE.fConstantWidth;
-		if ( SetLineAttribute( rE, rTransform.TransLineWidth( fW ) ) )
-		{
-			if ( ( rE.nFlags & 1 ) != 0 )
-				pVirDev->DrawPolygon( aPoly );
-			else
-				pVirDev->DrawPolyLine( aPoly );
-				// ####
-				//pVirDev->DrawPolyLine( aPoly, aDXFLineInfo );
-		}
+		// Fits in a single tools Polygon (which is indexed by sal_uInt16).
+		Polygon aPoly( (sal_uInt16)nPolySize );
+		for ( sal_Int32 i = 0; i < nPolySize; i++ )
+			rTransform.Transform( rE.pP[ i ], aPoly[ (sal_uInt16)i ] );
+		if ( bClosed )
+			pVirDev->DrawPolygon( aPoly );
+		else
+			pVirDev->DrawPolyLine( aPoly );
+		return;
+	}
+
+	// The DXF vertex count (group code 90) is a 32-bit value, but a tools Polygon
+	// holds at most 0xFFFF points. Render a larger polyline as a sequence of
+	// Polygon segments that overlap by one point, so the whole line is drawn
+	// without truncation and the stroke stays continuous. The source array pP is
+	// walked with the full 32-bit position; only the per-segment index is 16-bit.
+	const sal_Int32 nMaxChunk = 0xFFFF;
+	sal_Int32 nStart = 0;
+	while ( nStart + 1 < nPolySize )
+	{
+		sal_Int32 nEnd = nStart + nMaxChunk;
+		if ( nEnd > nPolySize )
+			nEnd = nPolySize;
+		const sal_uInt16 nChunk = (sal_uInt16)( nEnd - nStart );
+		Polygon aChunk( nChunk );
+		for ( sal_uInt16 j = 0; j < nChunk; j++ )
+			rTransform.Transform( rE.pP[ nStart + j ], aChunk[ j ] );
+		pVirDev->DrawPolyLine( aChunk );
+		nStart = nEnd - 1;   // next segment shares this segment's last point
+	}
+	if ( bClosed )
+	{
+		// Close the outline: last vertex back to the first.
+		Polygon aClose( 2 );
+		rTransform.Transform( rE.pP[ nPolySize - 1 ], aClose[ 0 ] );
+		rTransform.Transform( rE.pP[ 0 ],             aClose[ 1 ] );
+		pVirDev->DrawPolyLine( aClose );
 	}
 }