Fix title blocks with a line break writing an unreadable DXF

A title block cell holding a line break (tableau_domestique.qet's
"DESSINE" + CR LF + "%{author}") was written into the DXF as one TEXT
value with the break inside it. A DXF value ends at the line break, so
every group code after it was off by one line: ezdxf refuses all five
folios of that example with DXFStructureError, and other readers take
values for codes.

- TitleBlockTemplate::renderTextCellDxf() writes each line of a cell as
  its own TEXT, stacked by the cell's vertical alignment as the screen
  shows them, 1.6 text heights apart as the diagram texts' DXF export
  does. A single-line cell is written exactly as before.
- Createdxf's text writers turn any line break still in a value into a
  space, so no other caller can break the file either.

Checked in the Export dialog: tableau_domestique.qet's five folios, which
ezdxf refused on master, now read with no audit errors; grafcet.qet, which
has no line break, keeps exactly the same entities. (Byte comparison waits
on the DXF entity-order fix: until then every export reorders its entities.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G2d2Zi8BfrYRPX88zhaoFG
This commit is contained in:
ispyisail
2026-09-27 19:20:10 +13:00
parent 44cabbcfe4
commit 4efe28ce03
2 changed files with 64 additions and 24 deletions
+48 -22
View File
@@ -1993,32 +1993,58 @@ void TitleBlockTemplate::renderTextCellDxf(
}
//painter.setFont(text_font);
qreal ratio = 1.0;
if (cell.hadjust)
//A cell can hold several lines, which the screen shows one under the
//other (QPainter::drawText()). A DXF TEXT is a single line, and a line
//break inside one breaks the file (FINDINGS F052), so each line gets
//its own, stacked as the cell's vertical alignment says: the first at
//y1 when aligned to the top, the last at y1 when aligned to the
//bottom, the block centred on y1 otherwise. Spacing as the diagram
//texts' DXF export: 1.6 times the text height. A single line is
//written exactly as before.
const QStringList lines = text.split(QRegularExpression(QStringLiteral("\r\n|\r|\n")));
const qreal line_spacing = textHeight * Createdxf::yScale * 1.6;
const int last = lines.size() - 1;
for (int i = 0 ; i < lines.size() ; ++i)
{
// Scale font width to fit string in cell width w
// As DXF font aspect ratio is implementation dependent we add a fudge-factor based on tests with AutoCAD
int len = text.length() * textHeight * Createdxf::xScale * 1.2;
const QString &line = lines.at(i);
if (line.isEmpty()) continue;
if(len > w)
ratio = (w/len);
qreal offset; // upward, from y1
if (vAlign == 3)
offset = -i * line_spacing;
else if (vAlign == 2)
offset = (last / 2.0 - i) * line_spacing;
else
offset = (last - i) * line_spacing;
qreal ratio = 1.0;
if (cell.hadjust)
{
// Scale font width to fit string in cell width w
// As DXF font aspect ratio is implementation dependent we add a fudge-factor based on tests with AutoCAD
int len = line.length() * textHeight * Createdxf::xScale * 1.2;
if(len > w)
ratio = (w/len);
}
// x offset value below currently set heuristically based on appearance...
Createdxf::drawTextAligned(
file_path,
line,
x - 2*Createdxf::xScale,
y1 + offset,
textHeight*Createdxf::yScale,
0,
0,
hAlign,
vAlign,
x2,
ratio,
color);
}
// x offset value below currently set heuristically based on appearance...
Createdxf::drawTextAligned(
file_path,
text,
x - 2*Createdxf::xScale,
y1,
textHeight*Createdxf::yScale,
0,
0,
hAlign,
vAlign,
x2,
ratio,
color);
}
/**