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

ardovm pushed a commit to branch AOO41X
in repository https://gitbox.apache.org/repos/asf/openoffice.git


The following commit(s) were added to refs/heads/AOO41X by this push:
     new 3c5a7184f8 Merge pull request #491 from apache/bugfix-dxf-filter
3c5a7184f8 is described below

commit 3c5a7184f8642cf65c823667fcf4481e80301540
Author: Arrigo Marchiori <[email protected]>
AuthorDate: Tue Jul 28 22:11:12 2026 +0200

    Merge pull request #491 from apache/bugfix-dxf-filter
    
    Bugfix dxf filter
    
    (cherry pick and adaptation of merge commit
    c082241a9b512a7cac07a6b4facb9ec65953be75)
---
 .gitignore                                         |  17 +
 main/filter/source/graphicfilter/idxf/dxf2mtf.cxx  | 553 +++++++++++++++++----
 main/filter/source/graphicfilter/idxf/dxf2mtf.hxx  |   7 +
 main/filter/source/graphicfilter/idxf/dxfentrd.cxx | 166 ++++++-
 main/filter/source/graphicfilter/idxf/dxfentrd.hxx |  70 ++-
 main/filter/source/graphicfilter/idxf/dxfgrprd.cxx |  14 +-
 main/filter/source/graphicfilter/idxf/dxfreprd.cxx | 354 ++++++++++---
 main/filter/source/graphicfilter/idxf/dxftblrd.cxx |  20 +-
 main/filter/source/graphicfilter/idxf/dxfvec.cxx   |  13 +-
 main/filter/source/graphicfilter/idxf/idxf.cxx     |  19 +-
 main/filter/source/graphicfilter/idxf/makefile.mk  |   2 +-
 main/svtools/source/filter/filter.cxx              |  28 +-
 12 files changed, 1081 insertions(+), 182 deletions(-)

diff --git a/.gitignore b/.gitignore
index f541c96e3d..b14e7628ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,3 +84,20 @@ main/winaccessibility/source/UAccCOMIDL/dlldata.c
 
 # RepoRevision hash file
 /main/solenv/inc/reporevision.lst
+
+# Python
+.venv
+
+# Visual Studio Code
+.vscode/
+
+# JetBrains IDEs
+.idea/
+
+# claude
+.claude/
+
+# bazel
+bazel-*
+user.bazelrc
+*.lock
diff --git a/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx 
b/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx
index 734981d62a..8f8205f1b9 100644
--- a/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx
+++ b/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <vcl/gdimtf.hxx>
 #include <vcl/virdev.hxx>
+#include <vcl/hatch.hxx>
 #include <tools/poly.hxx>
 #include "dxf2mtf.hxx"
 
@@ -132,15 +133,23 @@ DXFLineInfo DXF2GDIMetaFile::LTypeToDXFLineInfo(const 
char * sLineType)
                }
        }
 
-#if 0
-       if (aDXFLineInfo.DashCount > 0 && aDXFLineInfo.DashLen == 0.0)
-               aDXFLineInfo.DashLen ( 1 );
-       if (aDXFLineInfo.DotCount > 0 && aDXFLineInfo.DotLen() == 0.0)
-               aDXFLineInfo.SetDotLen( 1 );
-       if (aDXFLineInfo.GetDashCount > 0 || aDXFLineInfo.GetDotCount > 0)
-               if (aDXFLineInfo.GetDistance() == 0)
-                       aDXFLineInfo.SetDistance( 1 );
-#endif
+       // A DXF pattern element of exactly 0.0 is a *dot* (a point), distinct 
from a
+       // positive-length dash (e.g. DOT2 = 0,-3.175). AutoCAD paints it as a 
small
+       // dot, but VCL has no round dot: LineInfo strokes every "on" run as a 
short
+       // segment, so a dot is just a very short dash. Rendered verbatim the 
length
+       // collapses to a sub-unit mark (Transform() only clamps it to 1/100mm) 
and the
+       // line came out invisible (issue 70275). Give a zero-length dot/dash a 
small
+       // model-unit length so it survives scaling; keep it a SMALL fraction 
of the
+       // gap (0.05) so it reads as a dot, not a dash. Done here in model 
units, not
+       // after scaling, so it tracks the drawing size. Only true 0.0 elements 
are
+       // adjusted — real authored dashes keep their length.
+       const double fDotOnFraction = 0.05;   // dot mark length as a fraction 
of the gap
+       if (aDXFLineInfo.fDistance != 0.0) {
+               if (aDXFLineInfo.nDotCount > 0 && aDXFLineInfo.fDotLen == 0.0)
+                       aDXFLineInfo.fDotLen = aDXFLineInfo.fDistance * 
fDotOnFraction;
+               if (aDXFLineInfo.nDashCount > 0 && aDXFLineInfo.fDashLen == 0.0)
+                       aDXFLineInfo.fDashLen = aDXFLineInfo.fDistance * 
fDotOnFraction;
+       }
 
        return aDXFLineInfo;
 }
@@ -475,6 +484,104 @@ void DXF2GDIMetaFile::DrawTextEntity(const DXFTextEntity 
& rE, const DXFTransfor
 }
 
 
+// Draw a TEXT entity projected into the (3D) view, used when the drawing is
+// rendered through a non-top viewport. VCL's DrawText can only place text 
with a
+// position + uniform height + single rotation, so it cannot follow the shear /
+// foreshortening a 3D projection produces. Instead we take the glyph OUTLINES 
and
+// push them through the full transform like any other geometry, so the text 
lies
+// in its projected plane. The flat 2D path (DrawTextEntity) is left untouched.
+void DXF2GDIMetaFile::Draw3DTextEntity(const DXFTextEntity & rE, const 
DXFTransform & rTransform)
+{
+       ByteString aStr( rE.sText );
+       String aUString( aStr, pDXF->getTextEncoding() );
+       if ( aUString.Len()==0 ) return;
+
+       long nColor = GetEntityColor(rE);
+       if ( nColor<0 ) return;
+       Color aColor = ConvertColor((sal_uInt8)nColor);
+
+       // Extract the glyph outlines from a SCRATCH device, never from 
pVirDev: the
+       // recording device has output disabled, so its GetTextOutlines falls 
back to a
+       // bitmap path that fails ("could not create system bitmap"). A clean 
scalable
+       // font on a plain VirtualDevice takes the vector path. The nominal 
height is
+       // arbitrary — the extent is self-calibrated below.
+       const long nNominal = 1000;
+       Font aFont;
+       aFont.SetFamily(FAMILY_SWISS);
+       aFont.SetSize(Size(0,nNominal));
+       aFont.SetAlign(ALIGN_BASELINE);
+       VirtualDevice aTextDev;
+       aTextDev.SetFont(aFont);
+       PolyPolyVector aGlyphs;
+       sal_Bool bOK = aTextDev.GetTextOutlines( aGlyphs, aUString );
+       if ( !bOK || aGlyphs.empty() ) {
+               DrawTextEntity(rE,rTransform);   // no outlines available -> 
flat fallback
+               return;
+       }
+
+       // GetTextOutlines returns the glyphs in an opaque internal scale (it 
toggles
+       // the map mode and rescales by a pixel factor), so we can't assume the 
height
+       // is nNominal. Self-calibrate: measure the real outline extent and 
normalise by
+       // its height, so one text-height maps to 1.0 regardless of the device 
scale.
+       double fMinY=0.0, fMaxY=0.0;
+       sal_Bool bFirst = sal_True;
+       sal_uInt32 g;
+       for ( g=0; g<aGlyphs.size(); g++ ) {
+               const PolyPolygon & rGlyph = aGlyphs[ g ];
+               sal_uInt16 c;
+               for ( c=0; c<rGlyph.Count(); c++ ) {
+                       const Polygon & rContour = rGlyph[ c ];
+                       sal_uInt16 i, nPts = rContour.GetSize();
+                       for ( i=0; i<nPts; i++ ) {
+                               const double y = (double)rContour[ i ].Y();
+                               if ( bFirst ) { fMinY=fMaxY=y; 
bFirst=sal_False; }
+                               else { if (y<fMinY) fMinY=y; if (y>fMaxY) 
fMaxY=y; }
+                       }
+               }
+       }
+       const double fHeight = fMaxY - fMinY;
+       if ( fHeight <= 0.0 ) {          // degenerate outlines -> flat fallback
+               DrawTextEntity(rE,rTransform);
+               return;
+       }
+       const double fInv = 1.0/fHeight;
+
+       // Text-local coords (baseline at Y=0, one text-height == 1.0, Y up) -> 
DXF
+       // text placement (width/height/rotation/insertion) -> the incoming 
extrusion+
+       // view transform. This is the same chain the renderer uses for 
geometry.
+       // The outlines are normalised to text-height units in BOTH axes, so X 
and Y
+       // must both scale by fHeight; fXScale (DXF group 41 width factor) is 
only an
+       // extra horizontal stretch on top (default 1.0). Scaling X by fXScale 
alone —
+       // as DrawTextEntity can, because it re-derives width from the font — 
would
+       // collapse the glyphs to a vertical sliver here.
+       const double fWScale = rE.fHeight * ( rE.fXScale>0.0 ? rE.fXScale : 1.0 
);
+       DXFTransform aT( 
DXFTransform(fWScale,rE.fHeight,1.0,rE.fRotAngle,rE.aP0), rTransform );
+
+       if ( aActFillColor!=aColor ) pVirDev->SetFillColor( aActFillColor = 
aColor );
+       if ( aActLineColor!=aColor ) pVirDev->SetLineColor( aActLineColor = 
aColor );
+
+       for ( g=0; g<aGlyphs.size(); g++ ) {
+               const PolyPolygon & rGlyph = aGlyphs[ g ];
+               PolyPolygon aDevGlyph;
+               sal_uInt16 c;
+               for ( c=0; c<rGlyph.Count(); c++ ) {
+                       const Polygon & rContour = rGlyph[ c ];
+                       sal_uInt16 nPts = rContour.GetSize();
+                       Polygon aDev( nPts );
+                       sal_uInt16 i;
+                       for ( i=0; i<nPts; i++ ) {
+                               const Point & rP = rContour[ i ];
+                               aT.Transform( DXFVector( (double)rP.X()*fInv,
+                                                                               
 -(double)rP.Y()*fInv, 0.0 ),
+                                                         aDev[ i ] );
+                       }
+                       aDevGlyph.Insert( aDev );
+               }
+               pVirDev->DrawPolyPolygon( aDevGlyph );
+       }
+}
+
+
 void DXF2GDIMetaFile::DrawInsertEntity(const DXFInsertEntity & rE, const 
DXFTransform & rTransform)
 {
        const DXFBlock * pB;
@@ -586,126 +693,331 @@ 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 nVtxCount = rE.nCount;
+       if ( nVtxCount <= 0 || rE.pP == NULL )
+               return;
+
+       double fW = rE.fConstantWidth;
+       if ( !SetLineAttribute( rE, rTransform.TransLineWidth( fW ) ) )
+               return;
+
+       const sal_Bool bClosed = ( rE.nFlags & 1 ) != 0;
+
+       // Build the outline in device space, expanding any segment that 
carries a
+       // non-zero bulge into an arc. In DXF a bulge is tan(sweep/4), so bulge 
1.0
+       // is a 180 degree arc; a circle is commonly stored as two bulged 
segments
+       // (e.g. Eagle CAD). Straight segments (bulge 0) contribute just the 
vertex.
+       DXFPointArray aPtAry;
+       Point aPt;
+       for ( sal_Int32 i = 0; i < nVtxCount; i++ )
        {
-               Polygon aPoly( (sal_uInt16)nPolySize);
-               for ( i = 0; i < nPolySize; i++ )
+               rTransform.Transform( rE.pP[ i ], aPt );
+               aPtAry.push_back( aPt );
+
+               sal_Int32 iNext = i + 1;
+               if ( iNext >= nVtxCount )
                {
-                       rTransform.Transform( rE.pP[ (sal_uInt16)i ], aPoly[ 
(sal_uInt16)i ] );
+                       if ( !bClosed ) break;   // open: no segment after the 
last vertex
+                       iNext = 0;               // closed: last vertex arcs 
back to the first
                }
-               double fW = rE.fConstantWidth;
-               if ( SetLineAttribute( rE, rTransform.TransLineWidth( fW ) ) )
+
+               const double fBulge = ( rE.pBulge != NULL ) ? rE.pBulge[ i ] : 
0.0;
+               if ( fBulge != 0.0 )
                {
-                       if ( ( rE.nFlags & 1 ) != 0 )
-                               pVirDev->DrawPolygon( aPoly );
-                       else
-                               pVirDev->DrawPolyLine( aPoly );
-                               // ####
-                               //pVirDev->DrawPolyLine( aPoly, aDXFLineInfo );
+                       const DXFVector & rS = rE.pP[ i ];
+                       const DXFVector & rEnd = rE.pP[ iNext ];
+                       // Arc centre from the bulge (cotangent form): the 
centre lies on the
+                       // chord's perpendicular bisector, offset by 
cot(sweep/2)/2 * chord.
+                       const double fCot = 0.5 * ( 1.0 / fBulge - fBulge );
+                       const double fCx = 0.5 * ( ( rS.fx + rEnd.fx ) + fCot * 
( rS.fy - rEnd.fy ) );
+                       const double fCy = 0.5 * ( ( rS.fy + rEnd.fy ) + fCot * 
( rEnd.fx - rS.fx ) );
+                       const double fRx = rS.fx - fCx;
+                       const double fRy = rS.fy - fCy;
+                       const double fRadius = sqrt( fRx * fRx + fRy * fRy );
+                       const double fStartAng = atan2( fRy, fRx );
+                       const double fSweep = 4.0 * atan( fBulge );   // 
signed: >0 = CCW
+                       sal_Int32 nArcPoints = (sal_Int32)( fabs( fSweep ) / ( 
2 * 3.14159265359 )
+                                                                               
                * (double)OptPointsPerCircle + 0.5 );
+                       // Emit the interior arc samples; the start vertex is 
already pushed
+                       // and the end vertex is pushed as the next loop's 
leading vertex.
+                       for ( sal_Int32 k = 1; k < nArcPoints; k++ )
+                       {
+                               const double fAng = fStartAng + fSweep * 
(double)k / (double)nArcPoints;
+                               rTransform.Transform(
+                                       DXFVector( fCx + fRadius * cos( fAng ),
+                                                          fCy + fRadius * sin( 
fAng ),
+                                                          rS.fz ),
+                                       aPt );
+                               aPtAry.push_back( aPt );
+                       }
                }
        }
+
+       const sal_Int32 nPolySize = (sal_Int32)aPtAry.size();
+       if ( nPolySize < 2 )
+               return;
+
+       if ( nPolySize <= 0xFFFF )
+       {
+               // 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++ )
+                       aPoly[ (sal_uInt16)i ] = aPtAry[ i ];
+               if ( bClosed )
+                       pVirDev->DrawPolygon( aPoly );
+               else
+                       pVirDev->DrawPolyLine( aPoly );
+               return;
+       }
+
+       // The tessellated outline can exceed the 0xFFFF points a tools Polygon 
holds.
+       // Render it as a sequence of Polygon segments that overlap by one 
point, so
+       // the whole line is drawn without truncation and the stroke stays 
continuous.
+       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++ )
+                       aChunk[ j ] = aPtAry[ nStart + j ];
+               pVirDev->DrawPolyLine( aChunk );
+               nStart = nEnd - 1;   // next segment shares this segment's last 
point
+       }
+       if ( bClosed )
+       {
+               // Close the outline: last point back to the first.
+               Polygon aClose( 2 );
+               aClose[ 0 ] = aPtAry[ nPolySize - 1 ];
+               aClose[ 1 ] = aPtAry[ 0 ];
+               pVirDev->DrawPolyLine( aClose );
+       }
 }
 
 void DXF2GDIMetaFile::DrawHatchEntity(const DXFHatchEntity & rE, const 
DXFTransform & rTransform )
 {
-       if ( rE.nBoundaryPathCount )
+       if ( !rE.nBoundaryPathCount )
+               return;
+
+       // Build the boundary as a PolyPolygon, tessellating curved edges so the
+       // area is measured correctly for both the solid fill and the pattern 
clip.
+       sal_Int32 j;
+       PolyPolygon aPolyPoly;
+       for ( j = 0; j < rE.nBoundaryPathCount; j++ )
        {
-               SetAreaAttribute( rE );
-               sal_Int32 j = 0;
-               PolyPolygon aPolyPoly;
-               for ( j = 0; j < rE.nBoundaryPathCount; j++ )
+               DXFPointArray aPtAry;
+               const DXFBoundaryPathData& rPathData = rE.pBoundaryPathData[ j 
];
+               if ( rPathData.bIsPolyLine )
                {
-                       DXFPointArray aPtAry;
-                       const DXFBoundaryPathData& rPathData = 
rE.pBoundaryPathData[ j ];
-                       if ( rPathData.bIsPolyLine )
+                       sal_Int32 i;
+                       for( i = 0; i < rPathData.nPointCount; i++ )
                        {
-                               sal_Int32 i;
-                               for( i = 0; i < rPathData.nPointCount; i++ )
-                               {
-                                       Point aPt;
-                                       rTransform.Transform( rPathData.pP[ i 
], aPt );
-                                       aPtAry.push_back( aPt );
-                               }
+                               Point aPt;
+                               rTransform.Transform( rPathData.pP[ i ], aPt );
+                               aPtAry.push_back( aPt );
                        }
-                       else
+               }
+               else
+               {
+                       sal_uInt32 i;
+                       for ( i = 0; i < rPathData.aEdges.size(); i++ )
                        {
-                               sal_uInt32 i;
-                               for ( i = 0; i < rPathData.aEdges.size(); i++ )
+                               const DXFEdgeType* pEdge = rPathData.aEdges[ i 
];
+                               switch( pEdge->nEdgeType )
                                {
-                                       const DXFEdgeType* pEdge = 
rPathData.aEdges[ i ];
-                                       switch( pEdge->nEdgeType )
+                                       case 1 :
                                        {
-                                               case 1 : 
+                                               Point aPt;
+                                               rTransform.Transform( 
((DXFEdgeTypeLine*)pEdge)->aStartPoint, aPt );
+                                               aPtAry.push_back( aPt );
+                                               rTransform.Transform( 
((DXFEdgeTypeLine*)pEdge)->aEndPoint, aPt );
+                                               aPtAry.push_back( aPt );
+                                       }
+                                       break;
+                                       case 2 :
+                                       {
+                                               // Circular arc edge: sample 
the sweep and push the points.
+                                               // Angles are in degrees; 
direction follows the CCW flag.
+                                               const DXFEdgeTypeCircularArc* 
pArc = (const DXFEdgeTypeCircularArc*)pEdge;
+                                               double fSweep = pArc->fEndAngle 
- pArc->fStartAngle;
+                                               if ( 
pArc->nIsCounterClockwiseFlag )
+                                                       { while ( fSweep <= 0.0 
) fSweep += 360.0; }
+                                               else
+                                                       { while ( fSweep >= 0.0 
) fSweep -= 360.0; }
+                                               sal_uInt16 nPts = (sal_uInt16)( 
fabs(fSweep)/360.0*(double)OptPointsPerCircle + 0.5 );
+                                               if ( nPts < 2 ) nPts = 2;
+                                               for ( sal_uInt16 k = 0; k < 
nPts; k++ )
                                                {
+                                                       double a = ( 
pArc->fStartAngle + fSweep*(double)k/(double)(nPts-1) )
+                                                                               
* (3.14159265359/180.0);
                                                        Point aPt;
-                                                       rTransform.Transform( 
((DXFEdgeTypeLine*)pEdge)->aStartPoint, aPt );
-                                                       aPtAry.push_back( aPt );
-                                                       rTransform.Transform( 
((DXFEdgeTypeLine*)pEdge)->aEndPoint, aPt );
+                                                       rTransform.Transform(
+                                                               DXFVector( 
pArc->aCenter.fx + pArc->fRadius*cos(a),
+                                                                               
   pArc->aCenter.fy + pArc->fRadius*sin(a), 0.0 ), aPt );
                                                        aPtAry.push_back( aPt );
                                                }
-                                               break;
-                                               case 2 :
-                                               {
-/*
-                                                       double 
frx,fry,fA1,fdA,fAng;
-                                                       sal_uInt16 nPoints,i;
-                                                       DXFVector aC;
-                                                       Point aPS,aPE;
-                                                       
fA1=((DXFEdgeTypeCircularArc*)pEdge)->fStartAngle;
-                                                       
fdA=((DXFEdgeTypeCircularArc*)pEdge)->fEndAngle - fA1;
-                                                       while ( fdA >= 360.0 )
-                                                               fdA -= 360.0;
-                                                       while ( fdA <= 0 )
-                                                               fdA += 360.0;
-                                                       
rTransform.Transform(((DXFEdgeTypeCircularArc*)pEdge)->aCenter, aC);
-                                                       if ( fdA > 5.0 && 
rTransform.TransCircleToEllipse(((DXFEdgeTypeCircularArc*)pEdge)->fRadius,frx,fry
 ) == sal_True )
-                                                       {
-                                                               DXFVector 
aVS(cos(fA1/180.0*3.14159265359),sin(fA1/180.0*3.14159265359),0.0);
-                                                               
aVS*=((DXFEdgeTypeCircularArc*)pEdge)->fRadius;
-                                                               
aVS+=((DXFEdgeTypeCircularArc*)pEdge)->aCenter;
-                                                               DXFVector 
aVE(cos((fA1+fdA)/180.0*3.14159265359),sin((fA1+fdA)/180.0*3.14159265359),0.0);
-                                                               
aVE*=((DXFEdgeTypeCircularArc*)pEdge)->fRadius;
-                                                               
aVE+=((DXFEdgeTypeCircularArc*)pEdge)->aCenter;
-                                                               if ( 
rTransform.Mirror() == sal_True )
-                                                               {
-                                                                       
rTransform.Transform(aVS,aPS);
-                                                                       
rTransform.Transform(aVE,aPE);
-                                                               }
-                                                               else
-                                                               {
-                                                                       
rTransform.Transform(aVS,aPE);
-                                                                       
rTransform.Transform(aVE,aPS);
-                                                               }
-                                                               
pVirDev->DrawArc(
-                                                                       
Rectangle((long)(aC.fx-frx+0.5),(long)(aC.fy-fry+0.5),
-                                                                               
          (long)(aC.fx+frx+0.5),(long)(aC.fy+fry+0.5)),
-                                                                       aPS,aPE
-                                                               );
-                                                       }
-*/
-                                               }
-                                               break;
-                                               case 3 :
-                                               case 4 :
-                                               break;
                                        }
+                                       break;
+                                       case 3 :        // elliptical arc: not 
tessellated (not seen in
+                                       case 4 :        // practice here); 
spline edges store no control
+                                       break;          // points, so both fall 
through as before.
                                }
                        }
-                       sal_uInt16 i, nSize = (sal_uInt16)aPtAry.size();
-                       if ( nSize )
-                       {
-                               Polygon aPoly( nSize );
-                               for ( i = 0; i < nSize; i++ )
-                                       aPoly[ i ] = aPtAry[ i ];
-                               aPolyPoly.Insert( aPoly, POLYPOLY_APPEND );
-                       }
                }
-               if ( aPolyPoly.Count() )
+               sal_uInt16 i, nSize = (sal_uInt16)aPtAry.size();
+               if ( nSize )
+               {
+                       Polygon aPoly( nSize );
+                       for ( i = 0; i < nSize; i++ )
+                               aPoly[ i ] = aPtAry[ i ];
+                       aPolyPoly.Insert( aPoly, POLYPOLY_APPEND );
+               }
+       }
+       if ( !aPolyPoly.Count() )
+               return;
+
+       if ( rE.nFlags & 1 )
+       {
+               // Solid fill (group 70 bit 0): flood-fill the boundary in the 
entity colour.
+               SetAreaAttribute( rE );
+               pVirDev->DrawPolyPolygon( aPolyPoly );
+       }
+       else if ( rE.bHasPatternLine )
+       {
+               // Pattern fill: render the section lines with VCL's DrawHatch, 
which
+               // clips a line family to the boundary and records a 
MetaHatchAction.
+               // The DXF pattern is collapsed to a single/double/triple 
Hatch; the
+               // on-page angle and spacing come from mapping the 
pattern-definition
+               // line's direction and inter-line offset through rTransform, 
so any
+               // scale / rotation / block-insert nesting is accounted for.
+               long nColor = GetEntityColor( rE );
+               if ( nColor < 0 )
+                       return;
+               Color aColor = ConvertColor( (sal_uInt8)nColor );
+
+               const double fPi = 3.14159265359;
+               double fA = rE.fPatternLineAngle * (fPi/180.0);
+               DXFVector aDir, aOff;
+               rTransform.TransDir( DXFVector( cos(fA), sin(fA), 0.0 ), aDir );
+               rTransform.TransDir( DXFVector( rE.fPatternLineOffsetX, 
rE.fPatternLineOffsetY, 0.0 ), aOff );
+
+               double fDirLen = sqrt( aDir.fx*aDir.fx + aDir.fy*aDir.fy );
+               if ( fDirLen < 1e-9 )
+               {
+                       // degenerate direction: fall back to a bare outline 
(no blob).
+                       SetLineAttribute( rE );
                        pVirDev->DrawPolyPolygon( aPolyPoly );
+                       return;
+               }
+
+               // Perpendicular spacing between adjacent lines in device 
space, and the
+               // device line angle. VCL's angle is measured in the recorded 
coordinate
+               // system with its positive direction as (cos,-sin), hence 
-aDir.fy.
+               double fDist = fabs( aOff.fx*aDir.fy - aOff.fy*aDir.fx ) / 
fDirLen;
+               long nDistance = (long)( fDist + 0.5 );
+               if ( nDistance < 1 ) nDistance = 1;
+
+               double fAngle = atan2( -aDir.fy, aDir.fx ) * 1800.0 / fPi;
+               long nAngle10 = (long)( fAngle + (fAngle < 0.0 ? -0.5 : 0.5) );
+               nAngle10 %= 1800;
+               if ( nAngle10 < 0 )
+                       nAngle10 += 1800;
+
+               HatchStyle eStyle = HATCH_SINGLE;
+               if ( rE.nHatchPatternDefinitionLines == 2 )
+                       eStyle = HATCH_DOUBLE;
+               else if ( rE.nHatchPatternDefinitionLines >= 3 )
+                       eStyle = HATCH_TRIPLE;
+
+               Hatch aHatch( eStyle, aColor, nDistance, (sal_uInt16)nAngle10 );
+               pVirDev->DrawHatch( aPolyPoly, aHatch );
+       }
+       else
+       {
+               // Pattern fill but no pattern-definition line was parsed: 
stroke the
+               // boundary outline only (transparent fill), never a solid blob.
+               SetLineAttribute( rE );
+               pVirDev->DrawPolyPolygon( aPolyPoly );
+       }
+}
+
+void DXF2GDIMetaFile::DrawEllipseEntity(const DXFEllipseEntity & rE, const 
DXFTransform & rTransform)
+{
+       if (SetLineAttribute(rE)==sal_False) return;
+
+       // Major axis vector (relative to centre) and the minor axis, which for 
the
+       // common planar case (extrusion 0,0,1) is ratio*(normal x major) =
+       // ratio*(-major.y, major.x, 0). A non-default extrusion is applied 
through
+       // rTransform by DrawEntities, so compute in the entity's own frame.
+       const DXFVector & aU = rE.aP1;
+       DXFVector aV(-aU.fy * rE.fRatio, aU.fx * rE.fRatio, 0.0);
+
+       double fSweep = rE.fEnd - rE.fStart;
+       while (fSweep <= 0.0)             fSweep += 2*3.14159265359;
+       while (fSweep >  2*3.14159265359) fSweep -= 2*3.14159265359;
+
+       sal_uInt16 nPoints = (sal_uInt16)( 
fSweep/(2*3.14159265359)*(double)OptPointsPerCircle + 0.5 );
+       if (nPoints<2) nPoints=2;
+
+       Polygon aPoly(nPoints);
+       for (sal_uInt16 i=0; i<nPoints; i++) {
+               double t = rE.fStart + fSweep*(double)i/(double)(nPoints-1);
+               rTransform.Transform( rE.aP0 + aU*cos(t) + aV*sin(t), aPoly[i] 
);
        }
+       pVirDev->DrawPolyLine(aPoly);
 }
 
+
+void DXF2GDIMetaFile::DrawSplineEntity(const DXFSplineEntity & rE, const 
DXFTransform & rTransform)
+{
+       // Non-uniform B-spline, evaluated with de Boor's algorithm and drawn 
as a
+       // polyline. Rational (weighted) splines are treated as non-rational 
(the
+       // weights are ignored) — sufficient for the planar curves this targets.
+       if ( rE.pControlPts==NULL || rE.pfKnots==NULL ) return;
+       const long p = rE.nDegree;
+       const long n = rE.nCtrlCount - 1;
+       if ( p < 1 || n < p ) return;
+       if ( rE.nKnotCount != rE.nCtrlCount + p + 1 ) return;   // not a 
clamped B-spline
+       if ( SetLineAttribute(rE)==sal_False ) return;
+
+       const double * U = rE.pfKnots;
+       const double u0 = U[p];
+       const double u1 = U[n+1];
+       if ( u1 <= u0 ) return;
+
+       long nPoints = rE.nCtrlCount * 8;
+       if (nPoints < 2)    nPoints = 2;
+       if (nPoints > 2000) nPoints = 2000;
+
+       Polygon aPoly((sal_uInt16)nPoints);
+       DXFVector * d = new DXFVector[p+1];
+       for (long i=0; i<nPoints; i++) {
+               double u = u0 + (u1-u0)*(double)i/(double)(nPoints-1);
+               if (u >= u1) u = u1 - (u1-u0)*1e-9;   // stay inside the last 
knot span
+
+               // knot span k with U[k] <= u < U[k+1], clamped to [p, n]
+               long k = p;
+               while (k < n && u >= U[k+1]) k++;
+
+               long j, r;
+               for (j=0; j<=p; j++) d[j] = rE.pControlPts[k-p+j];
+               for (r=1; r<=p; r++) {
+                       for (j=p; j>=r; j--) {
+                               double fDenom = U[k+1+j-r] - U[k-p+j];
+                               double a = (fDenom!=0.0) ? (u - 
U[k-p+j])/fDenom : 0.0;
+                               d[j] = d[j-1]*(1.0-a) + d[j]*a;
+                       }
+               }
+               rTransform.Transform(d[p], aPoly[(sal_uInt16)i]);
+       }
+       delete[] d;
+       pVirDev->DrawPolyLine(aPoly);
+}
+
+
 void DXF2GDIMetaFile::Draw3DFaceEntity(const DXF3DFaceEntity & rE, const 
DXFTransform & rTransform)
 {
        sal_uInt16 nN,i;
@@ -773,7 +1085,7 @@ void DXF2GDIMetaFile::DrawEntities(const DXFEntities & 
rEntities,
 
        while (pE!=NULL && bStatus==sal_True) {
                if (pE->nSpace==0) {
-                       if (pE->aExtrusion.fz==1.0) {
+                       if (pE->aExtrusion.fz==1.0 || DXFCoordsAreWCS(*pE)) {
                                pT=&rTransform;
                        }
                        else {
@@ -800,7 +1112,10 @@ void DXF2GDIMetaFile::DrawEntities(const DXFEntities & 
rEntities,
                                DrawSolidEntity((DXFSolidEntity&)*pE,*pT);
                                break;
                        case DXF_TEXT:
-                               DrawTextEntity((DXFTextEntity&)*pE,*pT);
+                               if (b3DText)
+                                       
Draw3DTextEntity((DXFTextEntity&)*pE,*pT);
+                               else
+                                       DrawTextEntity((DXFTextEntity&)*pE,*pT);
                                break;
                        case DXF_INSERT:
                                DrawInsertEntity((DXFInsertEntity&)*pE,*pT);
@@ -817,6 +1132,12 @@ void DXF2GDIMetaFile::DrawEntities(const DXFEntities & 
rEntities,
                        case DXF_HATCH :
                                DrawHatchEntity((DXFHatchEntity&)*pE, *pT);
                                break;
+                       case DXF_ELLIPSE:
+                               DrawEllipseEntity((DXFEllipseEntity&)*pE,*pT);
+                               break;
+                       case DXF_SPLINE:
+                               DrawSplineEntity((DXFSplineEntity&)*pE,*pT);
+                               break;
                        case DXF_3DFACE:
                                Draw3DFaceEntity((DXF3DFaceEntity&)*pE,*pT);
                                break;
@@ -900,6 +1221,9 @@ sal_Bool DXF2GDIMetaFile::Convert(const DXFRepresentation 
& rDXF, GDIMetaFile &
                if (pVPort->aDirection.fx==0 && pVPort->aDirection.fy==0)
                        pVPort=NULL;
        }
+       // A non-top viewport means the drawing is projected in 3D; text then 
has to be
+       // laid into that projection (Draw3DTextEntity) rather than drawn flat.
+       b3DText = (pVPort!=NULL) ? sal_True : sal_False;
 
        if (pVPort==NULL) {
                if (pDXF->aBoundingBox.bEmpty==sal_True)
@@ -912,21 +1236,32 @@ sal_Bool DXF2GDIMetaFile::Convert(const 
DXFRepresentation & rDXF, GDIMetaFile &
                                fScale = 0;  // -Wall added this...
                        }
                        else {
+                               // Leave a small margin around the drawing. The 
larger extent is
+                               // scaled to fill the 10000-unit target 
exactly, so geometry that
+                               // lies right on the extent (e.g. a drawing 
frame's outer line)
+                               // would otherwise sit precisely on the fit 
boundary and be
+                               // clipped. This surfaced once issue 58347 made 
the bounding box
+                               // a tight fit to the geometry; the margin 
keeps every edge inside
+                               // the fitted area (symmetric, so all four 
sides get breathing room).
+                               const double fMargin =
+                                       (fWidth>fHeight ? fWidth : fHeight) * 
0.01;
+                               const double fFitWidth  = fWidth  + 2.0*fMargin;
+                               const double fFitHeight = fHeight + 2.0*fMargin;
 //                             if (fWidth<500.0 || fHeight<500.0 || 
fWidth>32767.0 || fHeight>32767.0) {
-                                       if (fWidth>fHeight)
-                                               fScale=10000.0/fWidth;
+                                       if (fFitWidth>fFitHeight)
+                                               fScale=10000.0/fFitWidth;
                                        else
-                                               fScale=10000.0/fHeight;
+                                               fScale=10000.0/fFitHeight;
 //                             }
 //                             else
 //                                     fScale=1.0;
                                aTransform=DXFTransform(fScale,-fScale,fScale,
-                                                                               
DXFVector(-pDXF->aBoundingBox.fMinX*fScale,
-                                                                               
                   pDXF->aBoundingBox.fMaxY*fScale,
+                                                                               
DXFVector((fMargin-pDXF->aBoundingBox.fMinX)*fScale,
+                                                                               
                  (pDXF->aBoundingBox.fMaxY+fMargin)*fScale,
                                                                                
                  -pDXF->aBoundingBox.fMinZ*fScale));
+                               aPrefSize.Width() =(long)(fFitWidth*fScale+1.5);
+                               
aPrefSize.Height()=(long)(fFitHeight*fScale+1.5);
                        }
-                       aPrefSize.Width() =(long)(fWidth*fScale+1.5);
-                       aPrefSize.Height()=(long)(fHeight*fScale+1.5);
                }
        }
        else {
diff --git a/main/filter/source/graphicfilter/idxf/dxf2mtf.hxx 
b/main/filter/source/graphicfilter/idxf/dxf2mtf.hxx
index f92a9c6e2e..16ff35e952 100644
--- a/main/filter/source/graphicfilter/idxf/dxf2mtf.hxx
+++ b/main/filter/source/graphicfilter/idxf/dxf2mtf.hxx
@@ -57,6 +57,7 @@ private:
        Color           aActLineColor;
        Color           aActFillColor;
        Font            aActFont;
+       sal_Bool        b3DText;                // draw TEXT projected into the 
3D view (Draw3DTextEntity)
 
        sal_uLong CountEntities(const DXFEntities & rEntities);
 
@@ -91,6 +92,8 @@ private:
 
        void DrawTextEntity(const DXFTextEntity & rE, const DXFTransform & 
rTransform);
 
+       void Draw3DTextEntity(const DXFTextEntity & rE, const DXFTransform & 
rTransform);
+
        void DrawInsertEntity(const DXFInsertEntity & rE, const DXFTransform & 
rTransform);
 
        void DrawAttribEntity(const DXFAttribEntity & rE, const DXFTransform & 
rTransform);
@@ -105,6 +108,10 @@ private:
 
        void DrawHatchEntity( const DXFHatchEntity & rE, const DXFTransform & 
rTransform );
 
+       void DrawEllipseEntity( const DXFEllipseEntity & rE, const DXFTransform 
& rTransform );
+
+       void DrawSplineEntity( const DXFSplineEntity & rE, const DXFTransform & 
rTransform );
+
        void DrawEntities(const DXFEntities & rEntities,
                                          const DXFTransform & rTransform,
                                          sal_Bool bTopEntities);
diff --git a/main/filter/source/graphicfilter/idxf/dxfentrd.cxx 
b/main/filter/source/graphicfilter/idxf/dxfentrd.cxx
index 099f036f2f..27219f03b7 100644
--- a/main/filter/source/graphicfilter/idxf/dxfentrd.cxx
+++ b/main/filter/source/graphicfilter/idxf/dxfentrd.cxx
@@ -422,7 +422,8 @@ DXFLWPolyLineEntity::DXFLWPolyLineEntity() :
        fConstantWidth( 0.0 ),
        fStartWidth( 0.0 ),
        fEndWidth( 0.0 ),
-       pP( NULL )
+       pP( NULL ),
+       pBulge( NULL )
 {
 }
 
@@ -433,8 +434,22 @@ void DXFLWPolyLineEntity::EvaluateGroup( DXFGroupReader & 
rDGR )
                case 90 :
                {
                        nCount = rDGR.GetI();
-                       if ( nCount )
-                               pP = new DXFVector[ nCount ];
+                       if ( rDGR.GetStatus() && nCount >= 0 )
+                       {
+                               try
+                               {
+                                       pP = new DXFVector[ nCount ];
+                                       pBulge = new double[ nCount ];
+                                       for ( sal_Int32 i = 0; i < nCount; i++ )
+                                               pBulge[ i ] = 0.0;
+                               }
+                               catch (::std::bad_alloc)
+                               {
+                                       rDGR.SetError();
+                               }
+                       }
+                       else
+                               rDGR.SetError();
                }
                break;
                case 70: nFlags = rDGR.GetI(); break;
@@ -453,6 +468,14 @@ void DXFLWPolyLineEntity::EvaluateGroup( DXFGroupReader & 
rDGR )
                                pP[ nIndex++ ].fy = rDGR.GetF();
                }
                break;
+               case 42:
+               {
+                       // per-vertex bulge; follows the 10/20 pair of the 
vertex it
+                       // belongs to (nIndex has already advanced past that 
vertex).
+                       if ( pBulge && ( nIndex > 0 ) && ( nIndex <= nCount ) )
+                               pBulge[ nIndex - 1 ] = rDGR.GetF();
+               }
+               break;
                default: DXFBasicEntity::EvaluateGroup(rDGR);
        }
 }
@@ -460,6 +483,7 @@ void DXFLWPolyLineEntity::EvaluateGroup( DXFGroupReader & 
rDGR )
 DXFLWPolyLineEntity::~DXFLWPolyLineEntity()
 {
        delete[] pP;
+       delete[] pBulge;
 }
 
 //--------------------------DXFHatchEntity-------------------------------------
@@ -662,6 +686,7 @@ DXFHatchEntity::DXFHatchEntity() :
        DXFBasicEntity( DXF_HATCH ),
        bIsInBoundaryPathContext( sal_False ),
        nCurrentBoundaryPathIndex( -1 ),
+       bPatternLineOffsetSet( sal_False ),
        nFlags( 0 ),
        nAssociativityFlag( 0 ),
        nBoundaryPathCount( 0 ),
@@ -673,6 +698,10 @@ DXFHatchEntity::DXFHatchEntity() :
        nHatchPatternDefinitionLines( 0 ),
        fPixelSize( 1.0 ),
        nNumberOfSeedPoints( 0 ),
+       bHasPatternLine( sal_False ),
+       fPatternLineAngle( 0.0 ),
+       fPatternLineOffsetX( 0.0 ),
+       fPatternLineOffsetY( 0.0 ),
        pBoundaryPathData( NULL )
 {
 }
@@ -708,6 +737,21 @@ void DXFHatchEntity::EvaluateGroup( DXFGroupReader & rDGR )
                case 47 : fPixelSize = rDGR.GetF(); break;
                case 98 : nNumberOfSeedPoints = rDGR.GetI(); break;
 
+               // Pattern-definition lines (only present for a pattern fill, 
after 75).
+               // Capture the FIRST line's angle (53) and inter-line offset 
(45/46);
+               // 53/45/46 appear nowhere else in a HATCH, so intercepting 
them here is
+               // safe. Codes 43/44 (base point) are not needed for a VCL 
Hatch.
+               case 53 :
+                       if ( !bHasPatternLine ) { fPatternLineAngle = 
rDGR.GetF(); bHasPatternLine = sal_True; }
+                       break;
+               case 45 :
+                       if ( bHasPatternLine && !bPatternLineOffsetSet ) 
fPatternLineOffsetX = rDGR.GetF();
+                       break;
+               case 46 :
+                       if ( bHasPatternLine && !bPatternLineOffsetSet )
+                       { fPatternLineOffsetY = rDGR.GetF(); 
bPatternLineOffsetSet = sal_True; }
+                       break;
+
                //!! passthrough !!
                case 92 : nCurrentBoundaryPathIndex++;
                default:
@@ -809,6 +853,98 @@ void DXFDimensionEntity::EvaluateGroup(DXFGroupReader & 
rDGR)
 
 //---------------------------- DXFEntites 
--------------------------------------
 
+//--------------------------DXFEllipseEntity------------------------------------
+
+DXFEllipseEntity::DXFEllipseEntity() : DXFBasicEntity(DXF_ELLIPSE)
+{
+       fRatio = 1.0;
+       fStart = 0.0;
+       fEnd   = 2*3.14159265359;
+}
+
+void DXFEllipseEntity::EvaluateGroup(DXFGroupReader & rDGR)
+{
+       switch (rDGR.GetG()) {
+               case 10: aP0.fx=rDGR.GetF(); break;
+               case 20: aP0.fy=rDGR.GetF(); break;
+               case 30: aP0.fz=rDGR.GetF(); break;
+               case 11: aP1.fx=rDGR.GetF(); break;
+               case 21: aP1.fy=rDGR.GetF(); break;
+               case 31: aP1.fz=rDGR.GetF(); break;
+               case 40: fRatio=rDGR.GetF(); break;
+               case 41: fStart=rDGR.GetF(); break;
+               case 42: fEnd=rDGR.GetF(); break;
+               default: DXFBasicEntity::EvaluateGroup(rDGR);
+       }
+}
+
+//--------------------------DXFSplineEntity-------------------------------------
+
+DXFSplineEntity::DXFSplineEntity() :
+       DXFBasicEntity(DXF_SPLINE),
+       nFlags(0),
+       nDegree(0),
+       nKnotCount(0),
+       nCtrlCount(0),
+       nFitCount(0),
+       pfKnots(NULL),
+       pControlPts(NULL),
+       nKnotIndex(0),
+       nCtrlIndex(0)
+{
+}
+
+DXFSplineEntity::~DXFSplineEntity()
+{
+       delete[] pfKnots;
+       delete[] pControlPts;
+}
+
+void DXFSplineEntity::EvaluateGroup(DXFGroupReader & rDGR)
+{
+       switch (rDGR.GetG()) {
+               case 70: nFlags  = rDGR.GetI(); break;
+               case 71: nDegree = rDGR.GetI(); break;
+               case 72:
+                       nKnotCount = rDGR.GetI();
+                       if ( rDGR.GetStatus() && nKnotCount > 0 ) {
+                               try { pfKnots = new double[nKnotCount]; }
+                               catch (::std::bad_alloc) { rDGR.SetError(); }
+                       }
+                       else if ( nKnotCount < 0 )
+                               rDGR.SetError();
+                       break;
+               case 73:
+                       nCtrlCount = rDGR.GetI();
+                       if ( rDGR.GetStatus() && nCtrlCount > 0 ) {
+                               try { pControlPts = new DXFVector[nCtrlCount]; }
+                               catch (::std::bad_alloc) { rDGR.SetError(); }
+                       }
+                       else if ( nCtrlCount < 0 )
+                               rDGR.SetError();
+                       break;
+               case 74: nFitCount = rDGR.GetI(); break;
+               case 40:
+                       if ( pfKnots && nKnotIndex < nKnotCount )
+                               pfKnots[nKnotIndex++] = rDGR.GetF();
+                       break;
+               // control points are 3D (10/20/30); advance on the Z group
+               case 10:
+                       if ( pControlPts && nCtrlIndex < nCtrlCount )
+                               pControlPts[nCtrlIndex].fx = rDGR.GetF();
+                       break;
+               case 20:
+                       if ( pControlPts && nCtrlIndex < nCtrlCount )
+                               pControlPts[nCtrlIndex].fy = rDGR.GetF();
+                       break;
+               case 30:
+                       if ( pControlPts && nCtrlIndex < nCtrlCount )
+                               pControlPts[nCtrlIndex++].fz = rDGR.GetF();
+                       break;
+               default: DXFBasicEntity::EvaluateGroup(rDGR);
+       }
+}
+
 void DXFEntities::Read(DXFGroupReader & rDGR)
 {
        DXFBasicEntity * pE, * * ppSucc;
@@ -841,6 +977,8 @@ void DXFEntities::Read(DXFGroupReader & rDGR)
                else if (strcmp(rDGR.GetS(),"3DFACE"    )==0) pE=new 
DXF3DFaceEntity;
                else if (strcmp(rDGR.GetS(),"DIMENSION" )==0) pE=new 
DXFDimensionEntity;
                else if (strcmp(rDGR.GetS(),"HATCH"             )==0) pE=new 
DXFHatchEntity;
+               else if (strcmp(rDGR.GetS(),"ELLIPSE"   )==0) pE=new 
DXFEllipseEntity;
+               else if (strcmp(rDGR.GetS(),"SPLINE"    )==0) pE=new 
DXFSplineEntity;
                else
                {
                        do {
@@ -865,3 +1003,25 @@ void DXFEntities::Clear()
        }
 }
 
+sal_Bool DXFCoordsAreWCS(const DXFBasicEntity & rE)
+{
+       // See the header comment. For a LINE the extrusion only defines a 
thickness
+       // direction, never the endpoint positions; applying it scatters 3D 
wireframes
+       // (issue 99893) and inflates the bounding box (both must agree). 
ELLIPSE/SPLINE
+       // are intentionally NOT WCS here — DrawEllipseEntity/DrawSplineEntity 
compute in
+       // the entity's own frame and rely on the extrusion being applied.
+       switch (rE.eType) {
+               case DXF_LINE:
+               case DXF_POINT:
+               case DXF_3DFACE:
+                       return sal_True;
+               case DXF_POLYLINE:
+                       // 3D polyline / 3D mesh / polyface mesh store WCS 
vertices; a plain
+                       // 2D polyline is in OCS.
+                       return ( ((const DXFPolyLineEntity &)rE).nFlags & 
(8|16|64) ) != 0
+                                  ? sal_True : sal_False;
+               default:
+                       return sal_False;
+       }
+}
+
diff --git a/main/filter/source/graphicfilter/idxf/dxfentrd.hxx 
b/main/filter/source/graphicfilter/idxf/dxfentrd.hxx
index 949b58bf3a..ffe8d6fd51 100644
--- a/main/filter/source/graphicfilter/idxf/dxfentrd.hxx
+++ b/main/filter/source/graphicfilter/idxf/dxfentrd.hxx
@@ -53,7 +53,9 @@ enum DXFEntityType {
        DXF_3DFACE,
        DXF_DIMENSION,
        DXF_LWPOLYLINE,
-       DXF_HATCH
+       DXF_HATCH,
+       DXF_ELLIPSE,
+       DXF_SPLINE
 };
 
 
//------------------------------------------------------------------------------
@@ -369,6 +371,7 @@ class DXFLWPolyLineEntity : public DXFBasicEntity
                double          fEndWidth;              // 41
 
                DXFVector*      pP;
+               double*         pBulge;                 // 42 (per vertex; 
parallel to pP, 0.0 = straight segment)
 
                DXFLWPolyLineEntity();
                ~DXFLWPolyLineEntity();
@@ -465,6 +468,7 @@ class DXFHatchEntity : public DXFBasicEntity
 {
                sal_Bool        bIsInBoundaryPathContext;
                sal_Int32       nCurrentBoundaryPathIndex;
+               sal_Bool        bPatternLineOffsetSet;                  // 
transient parse state (first 45/46 captured)
 
        public :
 
@@ -481,6 +485,15 @@ class DXFHatchEntity : public DXFBasicEntity
                double          fPixelSize;                                     
        // 47
                sal_Int32       nNumberOfSeedPoints;                    // 98
 
+               // First pattern-definition line (78 block). Enough to drive a 
VCL Hatch
+               // (single/double/triple): the line angle (53) and the 
inter-line offset
+               // (45/46) give on-page angle + spacing; multi-line patterns 
collapse to
+               // this line's geometry plus the style from 
nHatchPatternDefinitionLines.
+               sal_Bool        bHasPatternLine;                                
// a 53 line angle was parsed
+               double          fPatternLineAngle;                              
// 53
+               double          fPatternLineOffsetX;                    // 45
+               double          fPatternLineOffsetY;                    // 46
+
                DXFBoundaryPathData* pBoundaryPathData;
 
                DXFHatchEntity();
@@ -492,6 +505,53 @@ class DXFHatchEntity : public DXFBasicEntity
 };
 
 
+//--------------------------Ellipse---------------------------------------------
+
+class DXFEllipseEntity : public DXFBasicEntity {
+
+public:
+
+       DXFVector aP0;   // 10,20,30  center
+       DXFVector aP1;   // 11,21,31  endpoint of the major axis, relative to 
center
+       double fRatio;   // 40        ratio of minor axis to major axis
+       double fStart;   // 41        start parameter (radians; 0 for a full 
ellipse)
+       double fEnd;     // 42        end parameter   (radians; 2*pi for a full 
ellipse)
+
+       DXFEllipseEntity();
+
+protected:
+
+       virtual void EvaluateGroup(DXFGroupReader & rDGR);
+};
+
+//--------------------------Spline----------------------------------------------
+
+class DXFSplineEntity : public DXFBasicEntity {
+
+public:
+
+       long nFlags;         // 70   bit 1=closed, 2=periodic, 4=rational, 
8=planar
+       long nDegree;        // 71
+       long nKnotCount;     // 72
+       long nCtrlCount;     // 73
+       long nFitCount;      // 74
+
+       double *    pfKnots;      // 40        (nKnotCount entries)
+       DXFVector * pControlPts;  // 10,20,30  (nCtrlCount entries)
+
+       DXFSplineEntity();
+       ~DXFSplineEntity();
+
+protected:
+
+       virtual void EvaluateGroup(DXFGroupReader & rDGR);
+
+private:
+
+       long nKnotIndex;
+       long nCtrlIndex;
+};
+
 
//--------------------------Vertex----------------------------------------------
 
 class DXFVertexEntity : public DXFBasicEntity {
@@ -577,6 +637,14 @@ public:
                // Loescht alle Entities
 };
 
+// True when an entity's stored coordinates are already in WCS, so the OCS
+// "arbitrary axis" (extrusion) transform must NOT be applied to them. Used by
+// BOTH the renderer (DrawEntities) and the bounding-box pass 
(CalcBoundingBox) so
+// they stay consistent: flat/planar entities (CIRCLE, ARC, TEXT, 2D POLYLINE,
+// LWPOLYLINE, INSERT, ...) are OCS and DO need the extrusion; inherently-3D
+// entities (LINE, POINT, 3DFACE, and a 3D polyline / mesh) carry WCS 
coordinates.
+sal_Bool DXFCoordsAreWCS(const DXFBasicEntity & rE);
+
 
//------------------------------------------------------------------------------
 //--------------------------------- inlines 
------------------------------------
 
//------------------------------------------------------------------------------
diff --git a/main/filter/source/graphicfilter/idxf/dxfgrprd.cxx 
b/main/filter/source/graphicfilter/idxf/dxfgrprd.cxx
index 6cb4d553b2..6210b18a06 100644
--- a/main/filter/source/graphicfilter/idxf/dxfgrprd.cxx
+++ b/main/filter/source/graphicfilter/idxf/dxfgrprd.cxx
@@ -151,7 +151,7 @@ sal_uInt16 DXFGroupReader::Read()
                        else if (nG< 140) ReadS( aTmp );
                        else if (nG< 148) F140_147[nG-140]=ReadF();
                        else if (nG< 170) ReadS( aTmp );
-                       else if (nG< 176) I170_175[nG-175]=ReadI();
+                       else if (nG< 176) I170_175[nG-170]=ReadI();
                        else if (nG< 180) ReadI();
                        else if (nG< 210) ReadS( aTmp );
                        else if (nG< 240) F210_239[nG-210]=ReadF();
@@ -325,6 +325,18 @@ long DXFGroupReader::ReadI()
        } while (*p>='0' && *p<='9');
 
        while (*p==0x20) p++;
+
+       // Tolerate an integer group value written in floating-point notation
+       // (e.g. "1.0"): some CAD applications (Pro/ENGINEER) emit integer group
+       // codes — such as the DIMSTYLE flags 71/72 — that way. Skip a trailing
+       // decimal fraction and keep the integer part; AutoCAD accepts this, 
whereas
+       // a strict reject aborts the whole import (issue 122565).
+       if (*p=='.') {
+               p++;
+               while (*p>='0' && *p<='9') p++;
+               while (*p==0x20) p++;
+       }
+
        if (*p!=0) {
                bStatus=sal_False;
                return 0;
diff --git a/main/filter/source/graphicfilter/idxf/dxfreprd.cxx 
b/main/filter/source/graphicfilter/idxf/dxfreprd.cxx
index 8307c80c42..f4efc46201 100644
--- a/main/filter/source/graphicfilter/idxf/dxfreprd.cxx
+++ b/main/filter/source/graphicfilter/idxf/dxfreprd.cxx
@@ -25,6 +25,10 @@
 #include "precompiled_filter.hxx"
 
 #include <string.h>
+#include <math.h>
+#include <tools/string.hxx>   // gsl_getSystemTextEncoding
+#include <rtl/tencinfo.h>     // rtl_getTextEncodingFromWindowsCodePage
+#include <rtl/string.h>       // rtl_str_compareIgnoreAsciiCase
 #include <dxfreprd.hxx>
 
 
@@ -135,7 +139,32 @@ void DXFPalette::SetColor(sal_uInt8 nIndex, sal_uInt8 
nRed, sal_uInt8 nGreen, sa
 
 DXFRepresentation::DXFRepresentation()
 {
-       setTextEncoding(RTL_TEXTENCODING_IBM_437);
+       // Default text encoding for a DXF that neither declares a $DWGCODEPAGE 
nor
+       // receives an override from the caller (see GraphicImport / 
FilterConfigItem).
+       // The historic hard-coded IBM_437 (DOS OEM) is almost never right for 
a modern
+       // DXF and garbles any high-bit text (issue 99892). Prefer the system 
encoding,
+       // which usually matches the locale the file came from (e.g. a Russian 
machine
+       // -> MS_1251).
+       //
+       // BUT the system encoding is not necessarily a legacy 8-bit code page 
any more:
+       // on Windows with the "Use Unicode UTF-8 for worldwide language 
support" option
+       // GetACP() returns 65001, and on modern Linux the locale is UTF-8 as 
well, so
+       // the system encoding is RTL_TEXTENCODING_UTF8. Legacy DXF text 
predates UTF-8
+       // and is never encoded that way (test13.dxf: windows-1252 Ä/ü/ß on a 
UTF-8 host
+       // came out as artefacts), so decoding those bytes as UTF-8 fails. When 
the
+       // system encoding is Unicode/unknown, fall back to windows-1252 — the 
most
+       // common encoding for untagged DXF and AOO's usual Western default 
(cf. the
+       // msfilter legacy importers); other scripts come from an explicit 
$DWGCODEPAGE
+       // or the Phase B chooser.
+       // Precedence: file $DWGCODEPAGE > caller override > this default.
+       rtl_TextEncoding eDefault = gsl_getSystemTextEncoding();
+       if ( eDefault == RTL_TEXTENCODING_UTF8 ||
+            eDefault == RTL_TEXTENCODING_UTF7 ||
+            eDefault == RTL_TEXTENCODING_UCS2 ||
+            eDefault == RTL_TEXTENCODING_UCS4 ||
+            eDefault == RTL_TEXTENCODING_DONTKNOW )
+               eDefault = RTL_TEXTENCODING_MS_1252;
+       setTextEncoding(eDefault);
         setGlobalLineTypeScale(1.0);
 }
 
@@ -176,13 +205,67 @@ sal_Bool DXFRepresentation::Read( SvStream & rIStream, 
sal_uInt16 nMinPercent, s
 
        delete pDGR;
 
-       if (bRes==sal_True && aBoundingBox.bEmpty==sal_True)
-               CalcBoundingBox(aEntities,aBoundingBox);
+       if (bRes==sal_True)
+       {
+               // The header $EXTMIN/$EXTMAX that ReadHeader collected into 
aBoundingBox
+               // are written by AutoCAD from the current view/regen state, 
not from a
+               // tight geometry fit, so they drift with the zoom level in 
effect when
+               // the file was saved (issue 58347: same drawing, different 
zoom, wrong
+               // import scale). Measure the real geometry extent and use that 
for the
+               // page-fit scaling instead. CalcBoundingBox now measures every 
entity
+               // type DrawEntities actually renders (HATCH included), so a 
non-empty
+               // geometry box is authoritative. The header extents are kept 
only as a
+               // last-resort fallback for the degenerate case where nothing 
measurable
+               // was drawn at all (empty geometry box).
+               DXFBoundingBox aGeometryBox;
+               CalcBoundingBox(aEntities,aGeometryBox);
+               if (aGeometryBox.bEmpty==sal_False)
+                       aBoundingBox=aGeometryBox;
+       }
 
        return bRes;
 }
 
 
+// Map a DXF $DWGCODEPAGE value to an rtl text encoding.
+// The values AutoCAD writes are "ANSI_<cp>" (e.g. ANSI_1252, ANSI_1251),
+// "DOS<cp>" (e.g. DOS932, DOS850) or a few named ones ("MACINTOSH", "UTF8").
+// For the ANSI_/DOS_ forms the trailing number IS the Windows code page, so we
+// extract it and let rtl resolve it (covers the whole family in one line 
instead
+// of the old single ANSI_932 special case). Returns RTL_TEXTENCODING_DONTKNOW
+// when the value is empty/unrecognised so the caller can keep its current
+// (default or caller-supplied) encoding.
+static rtl_TextEncoding DXFCodePageToTextEncoding(const char * pCodePage)
+{
+       if (pCodePage==NULL || *pCodePage==0)
+               return RTL_TEXTENCODING_DONTKNOW;
+
+       // find the first digit (start of the code-page number, if any)
+       const char * p = pCodePage;
+       while (*p!=0 && (*p<'0' || *p>'9'))
+               p++;
+       if (*p!=0) {
+               sal_uInt32 nCodePage = 0;
+               while (*p>='0' && *p<='9') {
+                       nCodePage = nCodePage*10 + (sal_uInt32)(*p-'0');
+                       p++;
+               }
+               rtl_TextEncoding eEnc = 
rtl_getTextEncodingFromWindowsCodePage(nCodePage);
+               if (eEnc!=RTL_TEXTENCODING_DONTKNOW)
+                       return eEnc;
+       }
+
+       // named values without a code-page number
+       if (rtl_str_compareIgnoreAsciiCase(pCodePage,"MACINTOSH")==0)
+               return RTL_TEXTENCODING_APPLE_ROMAN;
+       if (rtl_str_compareIgnoreAsciiCase(pCodePage,"UTF8")==0 ||
+           rtl_str_compareIgnoreAsciiCase(pCodePage,"UTF-8")==0)
+               return RTL_TEXTENCODING_UTF8;
+
+       return RTL_TEXTENCODING_DONTKNOW;
+}
+
+
 void DXFRepresentation::ReadHeader(DXFGroupReader & rDGR)
 {
 
@@ -208,15 +291,13 @@ void DXFRepresentation::ReadHeader(DXFGroupReader & rDGR)
                                  {
                                          rDGR.Read();
 
-                                         // FIXME: we really need a whole 
table of 
-                                         // $DWGCODEPAGE to encodings mappings
-                                         if ( 
(strcmp(rDGR.GetS(),"ANSI_932")==0) ||
-                                             
(strcmp(rDGR.GetS(),"ansi_932")==0) ||
-                                              
(strcmp(rDGR.GetS(),"DOS932")==0) ||
-                                              
(strcmp(rDGR.GetS(),"dos932")==0) )
-                                         {
-                                                 
setTextEncoding(RTL_TEXTENCODING_MS_932);
-                                         }
+                                         // The file declares its encoding: 
this is
+                                         // authoritative and overrides both 
the
+                                         // default and any caller-supplied 
override.
+                                         rtl_TextEncoding eEnc =
+                                                 
DXFCodePageToTextEncoding(rDGR.GetS());
+                                         if (eEnc!=RTL_TEXTENCODING_DONTKNOW)
+                                                 setTextEncoding(eEnc);
                                  }
                                 else if (strcmp(rDGR.GetS(),"$LTSCALE")==0)
                                  {
@@ -231,73 +312,150 @@ void DXFRepresentation::ReadHeader(DXFGroupReader & rDGR)
 }
 
 
+// Map a single OCS point of an entity to WCS via its extrusion, then add it to
+// the bounding box. The renderer (DXF2GDIMetaFile::DrawEntities) applies the
+// same ECS->WCS transform per entity, so the extent has to be measured in WCS
+// as well — otherwise drawings that use a non-default (e.g. negative-Z)
+// extrusion come out mis-scaled and offset (issue 16564: PL1CAFE.dxf reaches
+// OCS X=-10.88 on mirrored polylines that actually render near WCS X=+10.88).
+static inline void UnionOCS(DXFBoundingBox & rBox, const DXFTransform & rE2W,
+                                                       const DXFVector & rP)
+{
+       DXFVector aW;
+       rE2W.Transform(rP, aW);
+       rBox.Union(aW);
+}
+
+
+// Approximate the world-space extent of a single line of text and add it to
+// the bounding box, so labels sitting near the drawing edge are not cropped.
+// AOO renders TEXT/ATTRIB left-aligned on the baseline at the insertion point,
+// growing up and to the right (the justification codes are ignored by the
+// renderer, see DXF2GDIMetaFile::DrawTextEntity), so bound that rectangle,
+// rotated by the text angle. The per-character advance and descent are
+// deliberately generous fractions of the text height so the label never clips.
+// rE2W maps the (OCS) text rectangle to WCS so text on an extruded entity is
+// measured where it is drawn.
+static void UnionTextExtent(DXFBoundingBox & rBox, const DXFTransform & rE2W,
+                                                       const DXFVector & 
rInsert,
+                                                       double fHeight, double 
fXScale, double fRotAngle,
+                                                       const char * pText)
+{
+       if (fHeight <= 0.0) {
+               UnionOCS(rBox, rE2W, rInsert);
+               return;
+       }
+       if (fXScale <= 0.0)
+               fXScale = 1.0;
+
+       const size_t nLen = (pText != NULL) ? strlen(pText) : 0;
+       const double fWidth   = (double)nLen * 0.85 * fHeight * fXScale;
+       const double fAscent  = fHeight;
+       const double fDescent = 0.25 * fHeight;
+
+       const double fRad = fRotAngle * 3.14159265359 / 180.0;
+       const DXFVector aDir( cos(fRad),  sin(fRad), 0.0); // text direction
+       const DXFVector aUp (-sin(fRad),  cos(fRad), 0.0); // baseline normal 
(up)
+
+       for (int a = 0; a < 2; a++) {
+               const double fAlong = a ? fWidth : 0.0;
+               for (int b = 0; b < 2; b++) {
+                       const double fPerp = b ? fAscent : -fDescent;
+                       UnionOCS(rBox, rE2W, rInsert + aDir * fAlong + aUp * 
fPerp);
+               }
+       }
+}
+
+
 void DXFRepresentation::CalcBoundingBox(const DXFEntities & rEntities,
                                                                                
DXFBoundingBox & rBox)
 {
        DXFBasicEntity * pBE=rEntities.pFirst;
        while (pBE!=NULL) {
+               // The renderer builds an ECS->WCS transform from the entity's 
extrusion
+               // whenever it is not the default (DrawEntities checks fz != 
1.0); measure
+               // through the SAME transform so the box is in WCS, not raw 
OCS. Use the same
+               // WCS-vs-OCS rule as DrawEntities (DXFCoordsAreWCS): entities 
whose coords
+               // are already WCS (LINE/POINT/3DFACE/3D-polyline) must NOT be 
extruded, or
+               // the box is measured over scattered positions and comes out 
far too large
+               // (issue 99893/70273 — geometry then sits in a corner of an 
inflated page).
+               DXFTransform aE2W;                        // identity by default
+               if (pBE->aExtrusion.fz != 1.0 && !DXFCoordsAreWCS(*pBE))
+                       aE2W = DXFTransform(pBE->aExtrusion);
                switch (pBE->eType) {
                        case DXF_LINE: {
                                const DXFLineEntity * pE = (DXFLineEntity*)pBE;
-                               rBox.Union(pE->aP0);
-                               rBox.Union(pE->aP1);
+                               UnionOCS(rBox, aE2W, pE->aP0);
+                               UnionOCS(rBox, aE2W, pE->aP1);
                                break;
                        }
                        case DXF_POINT: {
                                const DXFPointEntity * pE = 
(DXFPointEntity*)pBE;
-                               rBox.Union(pE->aP0);
+                               UnionOCS(rBox, aE2W, pE->aP0);
                                break;
                        }
                        case DXF_CIRCLE: {
                                const DXFCircleEntity * pE = 
(DXFCircleEntity*)pBE;
-                               DXFVector aP;
-                               aP=pE->aP0;
-                               aP.fx-=pE->fRadius;
-                               aP.fy-=pE->fRadius;
-                               rBox.Union(aP);
-                               aP=pE->aP0;
-                               aP.fx+=pE->fRadius;
-                               aP.fy+=pE->fRadius;
-                               rBox.Union(aP);
+                               // radius is invariant under the extrusion (a 
rotation/reflection),
+                               // so map the centre to WCS and take +/-radius 
there.
+                               DXFVector aC;
+                               aE2W.Transform(pE->aP0, aC);
+                               DXFVector aP=aC; aP.fx-=pE->fRadius; 
aP.fy-=pE->fRadius; rBox.Union(aP);
+                               aP=aC; aP.fx+=pE->fRadius; aP.fy+=pE->fRadius; 
rBox.Union(aP);
                                break;
                        }
                        case DXF_ARC: {
                                const DXFArcEntity * pE = (DXFArcEntity*)pBE;
-                               DXFVector aP;
-                               aP=pE->aP0;
-                               aP.fx-=pE->fRadius;
-                               aP.fy-=pE->fRadius;
-                               rBox.Union(aP);
-                               aP=pE->aP0;
-                               aP.fx+=pE->fRadius;
-                               aP.fy+=pE->fRadius;
-                               rBox.Union(aP);
+                               // Measure the arc's SWEPT extent, not its full 
circle. A
+                               // large-radius arc (nearly straight, common in 
CAD) has its
+                               // centre far outside the drawing; unioning 
centre +/- radius
+                               // blew the box up enormously and collapsed the 
real geometry
+                               // (issue 122565). Sample along the sweep 
exactly as the renderer
+                               // does (CCW from fStart by fdA, normalised to 
(0,360]) and map
+                               // each point through the same ECS->WCS 
transform.
+                               double fA1 = pE->fStart;
+                               double fdA = pE->fEnd - fA1;
+                               while (fdA>=360.0) fdA-=360.0;
+                               while (fdA<=0.0)   fdA+=360.0;
+                               sal_uInt16 nSeg = (sal_uInt16)(fdA/4.0 + 0.5);
+                               if (nSeg<1) nSeg=1;
+                               for (sal_uInt16 nA=0; nA<=nSeg; nA++) {
+                                       double fAng = 3.14159265359/180.0 *
+                                                                 (fA1 + 
fdA*(double)nA/(double)nSeg);
+                                       UnionOCS(rBox, aE2W, pE->aP0 +
+                                                        
DXFVector(pE->fRadius*cos(fAng),
+                                                                          
pE->fRadius*sin(fAng), 0.0));
+                               }
                                break;
                        }
                        case DXF_TRACE: {
                                const DXFTraceEntity * pE = 
(DXFTraceEntity*)pBE;
-                               rBox.Union(pE->aP0);
-                               rBox.Union(pE->aP1);
-                               rBox.Union(pE->aP2);
-                               rBox.Union(pE->aP3);
+                               UnionOCS(rBox, aE2W, pE->aP0);
+                               UnionOCS(rBox, aE2W, pE->aP1);
+                               UnionOCS(rBox, aE2W, pE->aP2);
+                               UnionOCS(rBox, aE2W, pE->aP3);
                                break;
                        }
                        case DXF_SOLID: {
                                const DXFSolidEntity * pE = 
(DXFSolidEntity*)pBE;
-                               rBox.Union(pE->aP0);
-                               rBox.Union(pE->aP1);
-                               rBox.Union(pE->aP2);
-                               rBox.Union(pE->aP3);
+                               UnionOCS(rBox, aE2W, pE->aP0);
+                               UnionOCS(rBox, aE2W, pE->aP1);
+                               UnionOCS(rBox, aE2W, pE->aP2);
+                               UnionOCS(rBox, aE2W, pE->aP3);
                                break;
                        }
                        case DXF_TEXT: {
-                               //const DXFTextEntity * pE = 
(DXFTextEntity*)pBE;
-                               //???
+                               const DXFTextEntity * pE = (DXFTextEntity*)pBE;
+                               UnionTextExtent(rBox, aE2W, pE->aP0, 
pE->fHeight, pE->fXScale,
+                                                               pE->fRotAngle, 
pE->sText);
                                break;
                        }
                        case DXF_SHAPE: {
-                               //const DXFShapeEntity * pE = 
(DXFShapeEntity*)pBE;
-                               //???
+                               // SHAPE is not rendered (DrawEntities' 
dispatch has no case for
+                               // it, so DrawEntities falls through to 
default:break), therefore
+                               // it deliberately does not contribute to the 
extent — measuring
+                               // invisible geometry would only reserve empty 
margin and shrink
+                               // the visible drawing on the page.
                                break;
                        }
                        case DXF_INSERT: {
@@ -312,34 +470,37 @@ void DXFRepresentation::CalcBoundingBox(const DXFEntities 
& rEntities,
                                
aP.fx=(aBox.fMinX-pB->aBasePoint.fx)*pE->fXScale+pE->aP0.fx;
                                
aP.fy=(aBox.fMinY-pB->aBasePoint.fy)*pE->fYScale+pE->aP0.fy;
                                
aP.fz=(aBox.fMinZ-pB->aBasePoint.fz)*pE->fZScale+pE->aP0.fz;
-                               rBox.Union(aP);
+                               UnionOCS(rBox, aE2W, aP);
                                
aP.fx=(aBox.fMaxX-pB->aBasePoint.fx)*pE->fXScale+pE->aP0.fx;
                                
aP.fy=(aBox.fMaxY-pB->aBasePoint.fy)*pE->fYScale+pE->aP0.fy;
                                
aP.fz=(aBox.fMaxZ-pB->aBasePoint.fz)*pE->fZScale+pE->aP0.fz;
-                               rBox.Union(aP);
+                               UnionOCS(rBox, aE2W, aP);
                                break;
                        }
                        case DXF_ATTDEF: {
-                               //const DXFAttDefEntity * pE = 
(DXFAttDefEntity*)pBE;
-                               //???
+                               // ATTDEF (attribute definition) is likewise 
not rendered by
+                               // DrawEntities, so — like SHAPE — it is 
intentionally left out
+                               // of the extent to stay consistent with what 
actually gets
+                               // drawn.
                                break;
                        }
                        case DXF_ATTRIB: {
-                               //const DXFAttribEntity * pE = 
(DXFAttribEntity*)pBE;
-                               //???
+                               const DXFAttribEntity * pE = 
(DXFAttribEntity*)pBE;
+                               UnionTextExtent(rBox, aE2W, pE->aP0, 
pE->fHeight, pE->fXScale,
+                                                               pE->fRotAngle, 
pE->sText);
                                break;
                        }
                        case DXF_VERTEX: {
                                const DXFVertexEntity * pE = 
(DXFVertexEntity*)pBE;
-                               rBox.Union(pE->aP0);
+                               UnionOCS(rBox, aE2W, pE->aP0);
                                break;
                        }
                        case DXF_3DFACE: {
                                const DXF3DFaceEntity * pE = 
(DXF3DFaceEntity*)pBE;
-                               rBox.Union(pE->aP0);
-                               rBox.Union(pE->aP1);
-                               rBox.Union(pE->aP2);
-                               rBox.Union(pE->aP3);
+                               UnionOCS(rBox, aE2W, pE->aP0);
+                               UnionOCS(rBox, aE2W, pE->aP1);
+                               UnionOCS(rBox, aE2W, pE->aP2);
+                               UnionOCS(rBox, aE2W, pE->aP3);
                                break;
                        }
                        case DXF_DIMENSION: {
@@ -354,16 +515,18 @@ void DXFRepresentation::CalcBoundingBox(const DXFEntities 
& rEntities,
                                aP.fx=aBox.fMinX-pB->aBasePoint.fx;
                                aP.fy=aBox.fMinY-pB->aBasePoint.fy;
                                aP.fz=aBox.fMinZ-pB->aBasePoint.fz;
-                               rBox.Union(aP);
+                               UnionOCS(rBox, aE2W, aP);
                                aP.fx=aBox.fMaxX-pB->aBasePoint.fx;
                                aP.fy=aBox.fMaxY-pB->aBasePoint.fy;
                                aP.fz=aBox.fMaxZ-pB->aBasePoint.fz;
-                               rBox.Union(aP);
+                               UnionOCS(rBox, aE2W, aP);
                                break;
                        }
                        case DXF_POLYLINE: {
-                               //const DXFAttribEntity * pE = 
(DXFAttribEntity*)pBE;
-                               //???
+                               // The old-style POLYLINE header carries no 
coordinates itself;
+                               // its geometry lives in the VERTEX entities 
that follow it in
+                               // the entity list (each handled by the 
DXF_VERTEX case above),
+                               // so there is nothing to union here.
                                break;
                        }
                        case DXF_SEQEND: {
@@ -371,10 +534,77 @@ void DXFRepresentation::CalcBoundingBox(const DXFEntities 
& rEntities,
                                //???
                                break;
                        }
-                       case DXF_HATCH :
+                       case DXF_HATCH : {
+                               // HATCH is rendered (DrawHatchEntity), so its 
extent has to be
+                               // measured or a hatch reaching past the rest 
of the drawing gets
+                               // cropped. Union exactly the boundary geometry 
the renderer
+                               // actually draws: the points of a polyline 
boundary path, and
+                               // the endpoints of straight (type 1) edges. 
Circular-arc,
+                               // elliptical-arc and spline edges are NOT 
drawn by
+                               // DrawHatchEntity (their code is commented out 
/ empty), so they
+                               // are intentionally not unioned here — 
matching the render.
+                               const DXFHatchEntity * pE = 
(DXFHatchEntity*)pBE;
+                               for (sal_Int32 nPath = 0;
+                                        pE->pBoundaryPathData != NULL && nPath 
< pE->nBoundaryPathCount;
+                                        nPath++)
+                               {
+                                       const DXFBoundaryPathData & rPath = 
pE->pBoundaryPathData[nPath];
+                                       if (rPath.bIsPolyLine == sal_True) {
+                                               if (rPath.pP != NULL) {
+                                                       for (sal_Int32 i = 0; i 
< rPath.nPointCount; i++)
+                                                               UnionOCS(rBox, 
aE2W, rPath.pP[i]);
+                                               }
+                                       }
+                                       else {
+                                               for (size_t i = 0; i < 
rPath.aEdges.size(); i++) {
+                                                       const DXFEdgeType * 
pEdge = rPath.aEdges[i];
+                                                       if (pEdge != NULL && 
pEdge->nEdgeType == 1) {
+                                                               const 
DXFEdgeTypeLine * pLine = (DXFEdgeTypeLine*)pEdge;
+                                                               UnionOCS(rBox, 
aE2W, pLine->aStartPoint);
+                                                               UnionOCS(rBox, 
aE2W, pLine->aEndPoint);
+                                                       }
+                                               }
+                                       }
+                               }
                                break;
-                       case DXF_LWPOLYLINE :
+                       }
+                       case DXF_LWPOLYLINE : {
+                               // LWPOLYLINE keeps its vertices inline in pP[] 
(not as
+                               // separate VERTEX entities), so they must be 
unioned here
+                               // or the drawing extent misses the polyline 
and the graphic
+                               // is cropped. Walk the same [0,nCount) range 
that
+                               // DrawLWPolyLineEntity renders.
+                               const DXFLWPolyLineEntity * pE = 
(DXFLWPolyLineEntity*)pBE;
+                               if (pE->pP != NULL) {
+                                       for (sal_Int32 i = 0; i < pE->nCount; 
i++)
+                                               UnionOCS(rBox, aE2W, pE->pP[i]);
+                               }
                                break;
+                       }
+                       case DXF_ELLIPSE: {
+                               // Conservative full-ellipse AABB (like ARC 
uses the full-circle
+                               // box): centre +/- the axis-projected radii. 
Over-approximates a
+                               // partial ellipse, which is fine for a 
bounding box.
+                               const DXFEllipseEntity * pE = 
(DXFEllipseEntity*)pBE;
+                               const DXFVector & aU = pE->aP1;
+                               DXFVector aV(-aU.fy*pE->fRatio, 
aU.fx*pE->fRatio, 0.0);
+                               double fRx = sqrt(aU.fx*aU.fx + aV.fx*aV.fx);
+                               double fRy = sqrt(aU.fy*aU.fy + aV.fy*aV.fy);
+                               DXFVector aC;
+                               aE2W.Transform(pE->aP0, aC);
+                               DXFVector aP=aC; aP.fx-=fRx; aP.fy-=fRy; 
rBox.Union(aP);
+                               aP=aC; aP.fx+=fRx; aP.fy+=fRy; rBox.Union(aP);
+                               break;
+                       }
+                       case DXF_SPLINE: {
+                               // The control polygon's convex hull contains 
the B-spline curve,
+                               // so unioning the control points bounds it 
(conservatively).
+                               const DXFSplineEntity * pE = 
(DXFSplineEntity*)pBE;
+                               if (pE->pControlPts != NULL)
+                                       for (long i = 0; i < pE->nCtrlCount; 
i++)
+                                               UnionOCS(rBox, aE2W, 
pE->pControlPts[i]);
+                               break;
+                       }
                }
                pBE=pBE->pSucc;
        }
diff --git a/main/filter/source/graphicfilter/idxf/dxftblrd.cxx 
b/main/filter/source/graphicfilter/idxf/dxftblrd.cxx
index c7e266660e..c4c00feb81 100644
--- a/main/filter/source/graphicfilter/idxf/dxftblrd.cxx
+++ b/main/filter/source/graphicfilter/idxf/dxftblrd.cxx
@@ -332,11 +332,29 @@ DXFLayer * DXFTables::SearchLayer(const char * pName) 
const
 }
 
 
+// DXF symbol-table names (e.g. the "*ACTIVE" viewport) are case-insensitive, 
but
+// applications write them in different case ("*ACTIVE" vs "*Active"). A plain
+// strcmp then misses the active viewport, so idxf discards the saved view and
+// flattens a 3D drawing to a top-view. Compare ASCII-case-insensitively (names
+// are ASCII; this avoids <ctype.h>/locale and cherry-picks cleanly).
+static sal_Bool DXFNameEqualIgnoreCase(const char * p1, const char * p2)
+{
+       while (*p1!=0 && *p2!=0) {
+               char c1=*p1, c2=*p2;
+               if (c1>='A' && c1<='Z') c1 = (char)(c1 - 'A' + 'a');
+               if (c2>='A' && c2<='Z') c2 = (char)(c2 - 'A' + 'a');
+               if (c1!=c2) return sal_False;
+               p1++; p2++;
+       }
+       return (*p1==0 && *p2==0) ? sal_True : sal_False;
+}
+
+
 DXFVPort * DXFTables::SearchVPort(const char * pName) const
 {
        DXFVPort * p;
        for (p=pVPorts; p!=NULL; p=p->pSucc) {
-               if (strcmp(pName,p->sName)==0) break;
+               if (DXFNameEqualIgnoreCase(pName,p->sName)) break;
        }
        return p;
 }
diff --git a/main/filter/source/graphicfilter/idxf/dxfvec.cxx 
b/main/filter/source/graphicfilter/idxf/dxfvec.cxx
index fb0db28531..d8ba87de1c 100644
--- a/main/filter/source/graphicfilter/idxf/dxfvec.cxx
+++ b/main/filter/source/graphicfilter/idxf/dxfvec.cxx
@@ -245,6 +245,17 @@ double DXFTransform::CalcRotAngle() const
 
 sal_Bool DXFTransform::Mirror() const
 {
-       if (aMZ.SProd(aMX*aMY)<0) return sal_True; else return sal_False;
+       // True when this transform reverses orientation *in the projected XY 
plane* —
+       // the plane the 2D metafile is actually drawn in. Arc rendering uses 
this to
+       // choose the sweep direction handed to DrawArc.
+       //
+       // The 3D handedness aMZ.(aMX x aMY) is the wrong test here: a 
negative-Z
+       // extrusion feeds the Arbitrary Axis Algorithm a 180-degrees rotation 
about Y
+       // (a proper rotation), which flips the in-plane orientation yet leaves 
the 3D
+       // determinant sign unchanged (the flipped aMZ.z masks it). That drew 
arcs with
+       // negative-Z extrusion as their complement (e.g. a quarter arc as three
+       // quarters — issue 16564). Use the sign of the 2D projected 
determinant, which
+       // is what actually governs clockwise vs counter-clockwise on the page.
+       if (aMX.fx*aMY.fy - aMX.fy*aMY.fx < 0) return sal_True; else return 
sal_False;
 }
 
diff --git a/main/filter/source/graphicfilter/idxf/idxf.cxx 
b/main/filter/source/graphicfilter/idxf/idxf.cxx
index 31831d8c58..8112b10cc9 100644
--- a/main/filter/source/graphicfilter/idxf/idxf.cxx
+++ b/main/filter/source/graphicfilter/idxf/idxf.cxx
@@ -28,17 +28,34 @@
 #include <vcl/gdimtf.hxx>
 #include <vcl/graph.hxx>
 #include <vcl/virdev.hxx>
+#include <svtools/FilterConfigItem.hxx>
 #include "dxf2mtf.hxx"
 #include <math.h>
 
 //================== GraphicImport - die exportierte Funktion ================
 
-extern "C" sal_Bool __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic 
& rGraphic, FilterConfigItem*, sal_Bool )
+extern "C" sal_Bool __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic 
& rGraphic, FilterConfigItem* pConfigItem, sal_Bool )
 {
        DXFRepresentation aDXF;
        DXF2GDIMetaFile aConverter;
        GDIMetaFile aMTF;
 
+       // A DXF may not declare its text encoding ($DWGCODEPAGE). In that case 
the
+       // caller (a higher layer that knows the user's intent) can supply a 
fallback
+       // encoding as a "CharacterSet" filter option; it is applied before 
reading so
+       // that a $DWGCODEPAGE actually present in the file still wins over it.
+       // See idxf/cases/case-99892 (Phase B concept) for how this option is 
meant to
+       // be populated. When neither the file nor the caller provides one,
+       // DXFRepresentation defaults to the system ANSI encoding.
+       if ( pConfigItem )
+       {
+               sal_Int32 nEncoding = pConfigItem->ReadInt32(
+                       ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 
"CharacterSet" ) ),
+                       RTL_TEXTENCODING_DONTKNOW );
+               if ( nEncoding != RTL_TEXTENCODING_DONTKNOW )
+                       aDXF.setTextEncoding( (rtl_TextEncoding)nEncoding );
+       }
+
        if ( aDXF.Read( rStream, 0, 60 ) == sal_False )
                return sal_False;
        if ( aConverter.Convert( aDXF, aMTF, 60, 100 ) == sal_False )
diff --git a/main/filter/source/graphicfilter/idxf/makefile.mk 
b/main/filter/source/graphicfilter/idxf/makefile.mk
index 5d118d8854..1a0c478198 100644
--- a/main/filter/source/graphicfilter/idxf/makefile.mk
+++ b/main/filter/source/graphicfilter/idxf/makefile.mk
@@ -54,7 +54,7 @@ SLOFILES =  $(SLO)$/dxfgrprd.obj \
 
 SHL1TARGET=     idx$(DLLPOSTFIX)
 SHL1IMPLIB=     idxf
-SHL1STDLIBS=    $(VCLLIB) $(TOOLSLIB) $(SALLIB)
+SHL1STDLIBS=    $(VCLLIB) $(TOOLSLIB) $(SALLIB) $(SVTOOLLIB)
 .IF "$(GUI)" == "OS2"
 SHL1STDLIBS+=   $(CPPULIB)
 .ENDIF
diff --git a/main/svtools/source/filter/filter.cxx 
b/main/svtools/source/filter/filter.cxx
index 16878432fa..531d10fe62 100644
--- a/main/svtools/source/filter/filter.cxx
+++ b/main/svtools/source/filter/filter.cxx
@@ -514,8 +514,32 @@ static sal_Bool ImpPeekGraphicFormat( SvStream& rStream, 
String& rFormatExtensio
                bSomethingTested=sal_True;
 
                i=0;
-               while (i<256 && sFirstBytes[i]<=32)
-                       i++;
+
+               // A DXF file may begin with one or more 999 comment groups 
(each is a
+               // "999" code line followed by a comment value line), e.g. 
files written
+               // by Pro/ENGINEER. Skip them before looking for the first real 
group,
+               // otherwise such valid DXF files are rejected as an unknown 
format
+               // (issue 122565).
+               for (;;)
+               {
+                       while (i<256 && sFirstBytes[i]<=32)
+                               i++;
+                       if ( i+3<256 && sFirstBytes[i]=='9' && 
sFirstBytes[i+1]=='9' &&
+                                sFirstBytes[i+2]=='9' && sFirstBytes[i+3]<=32 )
+                       {
+                               // skip the "999" code line and the comment 
value line after it
+                               int nLine;
+                               for ( nLine=0; nLine<2 && i<256; nLine++ )
+                               {
+                                       while (i<256 && sFirstBytes[i]!='\n' && 
sFirstBytes[i]!='\r')
+                                               i++;
+                                       while (i<256 && (sFirstBytes[i]=='\n' 
|| sFirstBytes[i]=='\r'))
+                                               i++;
+                               }
+                               continue;
+                       }
+                       break;
+               }
 
                if (i<256)
                {

Reply via email to