[TD]Symbol scaling (fix #14400) (#18757)

* [TD]add legacy/new svg scaling pref

* [TD]Change Svg scaling logic (fix 14400)
This commit is contained in:
WandererFan
2025-01-06 12:02:37 -05:00
committed by GitHub
parent 9e6f3660e5
commit a3e49023d1
4 changed files with 86 additions and 14 deletions

View File

@@ -676,3 +676,9 @@ bool Preferences::switchOnClick()
{
return getPreferenceGroup("General")->GetBool("SwitchToWB", true);
}
//! if true, svg symbols will use the old scaling logic.
bool Preferences::useLegacySvgScaling()
{
return getPreferenceGroup("General")->GetBool("LegacySvgScaling", false);
}

View File

@@ -157,6 +157,8 @@ public:
static bool checkShapesBeforeUse();
static bool debugBadShape();
static bool useLegacySvgScaling();
};

View File

@@ -24,11 +24,12 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cmath>
# include <sstream>
# include <QGraphicsColorizeEffect>
# include <QGraphicsItem>
# include <QRectF>
# include <QRegularExpression>
# include <QRegularExpressionMatch>
#endif
#include <Base/Console.h>
@@ -105,22 +106,17 @@ void QGIViewSymbol::draw()
void QGIViewSymbol::drawSvg()
{
auto viewSymbol(dynamic_cast<TechDraw::DrawViewSymbol*>(getViewObject()));
if (!viewSymbol)
if (!viewSymbol) {
return;
}
double rezfactor = Rez::getRezFactor();
double scaling = viewSymbol->getScale();
double pxMm = 3.78;//96px/25.4mm ( CSS/SVG defined value of 96 pixels per inch)
// double pxMm = 3.54; //90px/25.4mm ( inkscape value version <= 0.91)
//some software uses different px/in, so symbol will need Scale adjusted.
//Arch/Draft views are in px and need to be scaled @ rezfactor px/mm to ensure proper representation
if (viewSymbol->isDerivedFrom(TechDraw::DrawViewArch::getClassTypeId())
|| viewSymbol->isDerivedFrom(TechDraw::DrawViewDraft::getClassTypeId())) {
scaling = scaling * rezfactor;
}
else {
scaling = scaling * rezfactor / pxMm;
double scaling{1};
if (Preferences::useLegacySvgScaling()) {
scaling = legacyScaler(viewSymbol);
} else {
scaling = symbolScaler(viewSymbol);
}
m_svgItem->setScale(scaling);
QByteArray qba(viewSymbol->Symbol.getValue(), strlen(viewSymbol->Symbol.getValue()));
@@ -162,3 +158,69 @@ void QGIViewSymbol::rotateView()
double rot = getViewObject()->Rotation.getValue();
m_displayArea->setRotation(-rot);
}
//! this is the original scaling logic as used in versions <= 1.0
//! it does not scale correctly for svg files that use mm units, but is available for
//! backwards compatibility. Set General/LegacySvgScaling to true to use this method.
double QGIViewSymbol::legacyScaler(TechDraw::DrawViewSymbol* feature) const
{
double rezfactor = Rez::getRezFactor();
double scaling = feature->getScale();
double pxMm = 3.78;//96px/25.4mm ( CSS/SVG defined value of 96 pixels per inch)
// double pxMm = 3.54; //90px/25.4mm ( inkscape value version <= 0.91)
//some software uses different px/in, so symbol will need Scale adjusted.
//Arch/Draft views are in px and need to be scaled @ rezfactor px/mm to ensure proper representation
if (feature->isDerivedFrom(TechDraw::DrawViewArch::getClassTypeId())
|| feature->isDerivedFrom(TechDraw::DrawViewDraft::getClassTypeId())) {
scaling = scaling * rezfactor;
}
else {
scaling = scaling * rezfactor / pxMm;
}
return scaling;
}
//! new symbol scaling logic as of v1.1
//! svg in mm scales correctly. svg in px will be drawn using scene units (0.1 mm)
//! as pixels.
double QGIViewSymbol::symbolScaler(TechDraw::DrawViewSymbol* feature) const
{
double scaling = feature->getScale();
double rezfactor = Rez::getRezFactor();
QByteArray qba(feature->Symbol.getValue(), strlen(feature->Symbol.getValue()));
QString qSymbolString = QString::fromUtf8(qba);
const QString pxToken{QString::fromUtf8("px")};
const QString mmToken{QString::fromUtf8("mm")};
// heightRegex finds (height="51.8309mm") in the svg text and returns the mm if present
QString heightRegex = QString::fromUtf8(R"(height=\"\d*\.?\d+([a-zA-Z]+)\")");
QRegularExpression reHeight(heightRegex);
QRegularExpressionMatch matchHeight = reHeight.match(qSymbolString);
QString matchUnits;
if (matchHeight.hasMatch()) {
auto capture0 = matchHeight.captured(0);
matchUnits = matchHeight.captured(1);
}
if (matchUnits.isEmpty() ||
matchUnits == pxToken) {
scaling *= rezfactor;
}
if (matchUnits == mmToken) {
auto svgSize = m_svgItem->renderer()->defaultSize();
auto vpSize = m_svgItem->renderer()->viewBox();
// wf: this calculation works, but I don't know why. :(
// hints here: https://stackoverflow.com/questions/49866474/get-svg-size-from-qsvgrenderer
// and here: https://stackoverflow.com/questions/7544921/qt-qgraphicssvgitem-renders-too-big-0-5-unit-on-each-side
scaling *= rezfactor * vpSize.width() / svgSize.width();
}
return scaling;
}

View File

@@ -59,6 +59,8 @@ public:
protected:
virtual void drawSvg();
void symbolToSvg(QByteArray qba);
double legacyScaler(TechDraw::DrawViewSymbol* feature) const;
double symbolScaler(TechDraw::DrawViewSymbol* feature) const;
QGDisplayArea* m_displayArea;
QGCustomSvg *m_svgItem;