[TD]fix text size & position on Svg export #9968

This commit is contained in:
wandererfan
2023-07-29 18:56:33 -04:00
committed by WandererFan
parent 4c4792a053
commit 20ee438746

View File

@@ -145,10 +145,13 @@ void QGIRichAnno::setTextItem()
// Base::Console().Message("QGIRA::setTextItem() - %s\n", getViewName());
TechDraw::DrawRichAnno* annoFeat = getFeature();
QString inHtml = QString::fromUtf8(annoFeat->AnnoText.getValue());
QRectF inRect = m_text->boundingRect();
double fontSize = m_text->font().pointSizeF();
QRegularExpression rxFontSize(QString::fromUtf8("font-size:([0-9]*)pt;"));
QRegularExpressionMatch match;
double mmPerPoint = 0.353; // 25.4 mm/in / 72 points/inch
double cssPxPerPoint = 16.0 / 12.0; // CSS says 12 pt text is 16 px high
double sceneUnitsPerPoint = Rez::getRezFactor() * mmPerPoint; // scene units per point: 3.53
int pos = 0;
QStringList findList;
@@ -159,15 +162,14 @@ void QGIRichAnno::setTextItem()
QString qsOldSize = match.captured(1);
QString repl = found;
double newSize = qsOldSize.toDouble();
double newSize = qsOldSize.toDouble(); // in points
// The font size in the QGraphicsTextItem html is interpreted differently
// in svg rendering compared to the screen or pdf? The calculation for
// screen/pdf makes sense (scene units) and mm/point makes sense for svg
// but the requirement to divide by 2 is a mystery.
// in svg rendering compared to the screen or pdf?
if (getExportingSvg()) {
newSize = newSize / ( 2.0 * mmPerPoint);
// scale point size to CSS pixels
newSize = newSize * cssPxPerPoint;
} else {
// scale point size to scene units
newSize = newSize * sceneUnitsPerPoint;
}
QString qsNewSize = QString::number(newSize, 'f', 2);
@@ -182,37 +184,80 @@ void QGIRichAnno::setTextItem()
outHtml = outHtml.replace(findList[iRepl], replList[iRepl]);
}
prepareGeometryChange();
double actualWidth = m_text->textWidth();
m_text->setTextWidth(Rez::guiX(annoFeat->MaxWidth.getValue()));
m_text->setHtml(outHtml);
if (getExportingSvg()) {
m_text->setTextWidth(actualWidth);
// lines are correctly spaced on screen or in pdf, but svg needs this
setLineSpacing(100);
}
if (annoFeat->ShowFrame.getValue()) {
QRectF r = m_text->boundingRect().adjusted(1, 1,-1, -1);
QRectF outRect = m_text->boundingRect().adjusted(1, 1,-1, -1);
m_rect->setPen(rectPen());
m_rect->setBrush(Qt::NoBrush);
m_rect->setRect(r);
m_rect->setRect(outRect);
if (getExportingSvg()) {
// the original text bounding rect is closer to the right size vs
// the bounding rect after the text size is changed
m_rect->setRect(inRect);
}
m_rect->centerAt(0.0, 0.0);
m_rect->show();
} else {
m_rect->hide();
}
m_text->centerAt(0.0, 0.0);
m_rect->centerAt(0.0, 0.0);
if (getExportingSvg()) {
// m_text position will be wrong in svg, but m_rect will be correct, so
// we adjust the position of m_text
// double spaced default font size in px
double verticalAdjust = cssPxPerPoint * fontSize * 2.0;
QPointF textPos(m_rect->pos().x() + 1.0, m_rect->pos().y() + verticalAdjust);
m_text->setPos(textPos);
}
}
// attempt to space the lines correctly after the font sizes are changed to match
// the Svg rendering of the QGraphicsTextItem.
void QGIRichAnno::setLineSpacing(int lineSpacing)
{
//this line spacing should be px, but seems to be %? in any event, it does
//space out the lines
// left to itself, Qt appears to space the lines according to this formula
// DeltaY(in mm) = (1 + 2*pointSize + margin) which vastly under spaces the
// lines
m_text->document()->setUseDesignMetrics(true);
QTextBlock block = m_text->document()->begin();
for (; block.isValid(); block = block.next()) {
QTextCursor tc = QTextCursor(block);
QTextBlockFormat fmt = block.blockFormat();
fmt.setBottomMargin(lineSpacing); //spaces out the lines!
tc.setBlockFormat(fmt);
QTextBlockFormat fmt = tc.blockFormat();
QTextCharFormat cFmt = tc.charFormat();
// this is already converted to pixels in setTextItem
//
double cssPixelSize = cFmt.font().pointSizeF();
// css Pixels are treated as if they were points in the conversion to Svg
double textHeightSU = Rez::guiX(cssPixelSize * 25.4 / 72.0); // actual height of text in scene units
double pointSize = cssPixelSize * 72.0 / 96.0;
double deltaYSU = 1.0 + 2.0 * pointSize; // how far Qt will space lines (based on samples)
double linegap = 0.4 * cssPixelSize; // 20% gaps above and below
// margins will be included in Qt's calculation of spacing
double margin = linegap * pointSize / 10.0;
QTextBlockFormat spacerFmt = QTextBlockFormat();
if (block.previous().isValid()) {
// there is a block before this one, so add a top margin
spacerFmt.setTopMargin(margin);
}
if (block.next().isValid()) {
// there is another block after this, so add a bottom margin
spacerFmt.setBottomMargin(margin);
}
double requiredSpacing = (textHeightSU / (deltaYSU - 1.0)) * lineSpacing;
spacerFmt.setLineHeight(requiredSpacing, QTextBlockFormat::ProportionalHeight);
tc.mergeBlockFormat(spacerFmt);
}
}