"""표제란 SVG 서명을 CAD 폴리선으로 바꾸는 경로 검사 (2026-09-03 사용자 결정). 종전에는 `ImageEntity`(data URL)로 들어가 DXF 로 나가면 래스터가 됐다. SVG 만 벡터로 바꾸고 PNG·JPG 는 그대로 그림으로 둔다. """ from base64 import b64encode from B07_DesignDetail.B07_DesignDetail_Engine_Cad_Svg import fit_polylines, svg_polylines from B07_DesignDetail.B07_DesignDetail_Engine_Template import _vectorize_svg_image SIGN_SVG = ( '' '' '' "" ) def _image_entity(payload: str, mime: str = "image/svg+xml") -> dict: return { "id": "sign-1", "type": "Image", "lineColor": "#101010", "lineWidth": 1, "layerId": "title", "shapeData": { "points": [ {"x": 10.0, "y": 20.0}, {"x": 50.0, "y": 20.0}, {"x": 50.0, "y": 40.0}, {"x": 10.0, "y": 40.0}, ], "imageData": f"data:{mime};base64,{b64encode(payload.encode()).decode()}", }, } def test_svg_polylines_reads_path_and_polyline(): view_box, runs = svg_polylines(SIGN_SVG) assert view_box == (0.0, 0.0, 100.0, 50.0) assert len(runs) == 2 assert runs[0][0] == (10.0, 40.0) and runs[0][-1] == (50.0, 40.0) def test_fit_keeps_aspect_and_flips_y(): """비율을 지키고 세로를 뒤집는다 — SVG 는 y 가 아래로, 도면은 위로 자란다.""" view_box, runs = svg_polylines(SIGN_SVG) fitted = fit_polylines(runs, view_box, (10.0, 20.0, 50.0, 40.0)) xs = [x for run in fitted for x, _y in run] ys = [y for run in fitted for _x, y in run] assert 10.0 - 1e-9 <= min(xs) and max(xs) <= 50.0 + 1e-9 assert 20.0 - 1e-9 <= min(ys) and max(ys) <= 40.0 + 1e-9 # SVG 에서 y=10(위)이던 꼭짓점이 도면에서는 가장 높은 y 가 된다. assert fitted[0][1][1] > fitted[0][0][1] def test_image_entity_becomes_polylines(): result = _vectorize_svg_image(_image_entity(SIGN_SVG)) assert all(entity["type"] == "PolyLine" for entity in result) assert len(result) == 2 assert all(entity["layerId"] == "title" for entity in result) assert result[0]["children"], "폴리선에 선분이 없다" def test_raster_image_is_left_alone(): raster = _image_entity("not-svg", mime="image/png") assert _vectorize_svg_image(raster) == [raster] def test_broken_svg_keeps_image(): broken = _image_entity("