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 f51738dbca7116cbff1f2bdb0c6aa4a68d856359 Author: Peter Kovacs <[email protected]> AuthorDate: Sun Jul 5 09:41:51 2026 +0200 fix zoom by ignoring the metadata. The correctness of the metadata depends on creators actions and may be stale. Better to calculate it by ourselfs. --- main/filter/source/graphicfilter/idxf/dxf2mtf.cxx | 25 +++++--- main/filter/source/graphicfilter/idxf/dxfreprd.cxx | 72 +++++++++++++++++++--- 2 files changed, 81 insertions(+), 16 deletions(-) diff --git a/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx b/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx index 3ee67f6797..477b2c1b0a 100644 --- a/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx +++ b/main/filter/source/graphicfilter/idxf/dxf2mtf.cxx @@ -943,21 +943,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/dxfreprd.cxx b/main/filter/source/graphicfilter/idxf/dxfreprd.cxx index f35b544c6f..4fd7c62039 100644 --- a/main/filter/source/graphicfilter/idxf/dxfreprd.cxx +++ b/main/filter/source/graphicfilter/idxf/dxfreprd.cxx @@ -177,8 +177,23 @@ 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; } @@ -335,8 +350,11 @@ void DXFRepresentation::CalcBoundingBox(const DXFEntities & rEntities, 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: { @@ -359,8 +377,10 @@ void DXFRepresentation::CalcBoundingBox(const DXFEntities & rEntities, 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: { @@ -402,8 +422,10 @@ void DXFRepresentation::CalcBoundingBox(const DXFEntities & rEntities, 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: { @@ -411,8 +433,40 @@ 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++) + rBox.Union(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; + rBox.Union(pLine->aStartPoint); + rBox.Union(pLine->aEndPoint); + } + } + } + } break; + } case DXF_LWPOLYLINE : { // LWPOLYLINE keeps its vertices inline in pP[] (not as // separate VERTEX entities), so they must be unioned here
