diff --git a/src/Mod/TechDraw/App/Preferences.cpp b/src/Mod/TechDraw/App/Preferences.cpp index 53096b6910..6577a700fe 100644 --- a/src/Mod/TechDraw/App/Preferences.cpp +++ b/src/Mod/TechDraw/App/Preferences.cpp @@ -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); +} diff --git a/src/Mod/TechDraw/App/Preferences.h b/src/Mod/TechDraw/App/Preferences.h index 2d1a99476f..2a62f585bc 100644 --- a/src/Mod/TechDraw/App/Preferences.h +++ b/src/Mod/TechDraw/App/Preferences.h @@ -157,6 +157,8 @@ public: static bool checkShapesBeforeUse(); static bool debugBadShape(); + static bool useLegacySvgScaling(); + }; diff --git a/src/Mod/TechDraw/Gui/QGIViewSymbol.cpp b/src/Mod/TechDraw/Gui/QGIViewSymbol.cpp index af1fa299e7..aa5c9fccbf 100644 --- a/src/Mod/TechDraw/Gui/QGIViewSymbol.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewSymbol.cpp @@ -24,11 +24,12 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include -# include # include # include # include +# include +# include #endif #include @@ -105,22 +106,17 @@ void QGIViewSymbol::draw() void QGIViewSymbol::drawSvg() { auto viewSymbol(dynamic_cast(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; +} + + diff --git a/src/Mod/TechDraw/Gui/QGIViewSymbol.h b/src/Mod/TechDraw/Gui/QGIViewSymbol.h index 5283868220..e22182a6e1 100644 --- a/src/Mod/TechDraw/Gui/QGIViewSymbol.h +++ b/src/Mod/TechDraw/Gui/QGIViewSymbol.h @@ -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;