diff --git a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp index 3be9081511..35dbcb1480 100644 --- a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp @@ -1190,12 +1190,12 @@ private: { *rectToCheck = convertFromHostBounds (*rectToCheck); - auto scale = editor->getTransform().getScaleFactor(); + auto transformScale = std::sqrt (std::abs (editor->getTransform().getDeterminant())); - auto minW = (double) (constrainer->getMinimumWidth() * scale); - auto maxW = (double) (constrainer->getMaximumWidth() * scale); - auto minH = (double) (constrainer->getMinimumHeight() * scale); - auto maxH = (double) (constrainer->getMaximumHeight() * scale); + auto minW = (double) (constrainer->getMinimumWidth() * transformScale); + auto maxW = (double) (constrainer->getMaximumWidth() * transformScale); + auto minH = (double) (constrainer->getMinimumHeight() * transformScale); + auto maxH = (double) (constrainer->getMaximumHeight() * transformScale); auto width = (double) (rectToCheck->right - rectToCheck->left); auto height = (double) (rectToCheck->bottom - rectToCheck->top); diff --git a/modules/juce_graphics/geometry/juce_AffineTransform.cpp b/modules/juce_graphics/geometry/juce_AffineTransform.cpp index 588253f091..ceb15deb6a 100644 --- a/modules/juce_graphics/geometry/juce_AffineTransform.cpp +++ b/modules/juce_graphics/geometry/juce_AffineTransform.cpp @@ -236,9 +236,46 @@ bool AffineTransform::isOnlyTranslation() const noexcept && mat11 == 1.0f; } +float AffineTransform::getDeterminant() const noexcept +{ + return (mat00 * mat11) - (mat01 * mat10); +} + float AffineTransform::getScaleFactor() const noexcept { return (std::abs (mat00) + std::abs (mat11)) / 2.0f; } + +//============================================================================== +//============================================================================== +#if JUCE_UNIT_TESTS + +class AffineTransformTests : public UnitTest +{ +public: + AffineTransformTests() + : UnitTest ("AffineTransform", UnitTestCategories::maths) + {} + + void runTest() override + { + beginTest ("Determinant"); + { + constexpr float scale1 = 1.5f, scale2 = 1.3f; + + auto transform = AffineTransform::scale (scale1) + .followedBy (AffineTransform::rotation (degreesToRadians (72.0f))) + .followedBy (AffineTransform::translation (100.0f, 20.0f)) + .followedBy (AffineTransform::scale (scale2)); + + expect (approximatelyEqual (std::sqrt (std::abs (transform.getDeterminant())), scale1 * scale2)); + } + } +}; + +static AffineTransformTests timeTests; + +#endif + } // namespace juce diff --git a/modules/juce_graphics/geometry/juce_AffineTransform.h b/modules/juce_graphics/geometry/juce_AffineTransform.h index 06452d4990..66b87d378a 100644 --- a/modules/juce_graphics/geometry/juce_AffineTransform.h +++ b/modules/juce_graphics/geometry/juce_AffineTransform.h @@ -264,11 +264,23 @@ public: */ float getTranslationY() const noexcept { return mat12; } - /** Returns the approximate scale factor by which lengths will be transformed. + /** Returns the determinant of the transform. */ + float getDeterminant() const noexcept; + + /** This method has been deprecated. + + You can calculate the scale factor using: + @code + std::sqrt (std::abs (AffineTransform::getDeterminant())) + @endcode + + This method produces incorrect values for transforms containing rotations. + + Returns the approximate scale factor by which lengths will be transformed. Obviously a length may be scaled by entirely different amounts depending on its direction, so this is only appropriate as a rough guide. */ - float getScaleFactor() const noexcept; + JUCE_DEPRECATED (float getScaleFactor() const noexcept); /* A ready-to-use identity transform - now deprecated. @deprecated If you need an identity transform, just use AffineTransform() or {}. diff --git a/modules/juce_graphics/native/juce_RenderingHelpers.h b/modules/juce_graphics/native/juce_RenderingHelpers.h index 0935b2d1e0..d194f638ab 100644 --- a/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -96,7 +96,7 @@ public: float getPhysicalPixelScaleFactor() const noexcept { - return isOnlyTranslated ? 1.0f : std::abs (complexTransform.getScaleFactor()); + return isOnlyTranslated ? 1.0f : std::sqrt (std::abs (complexTransform.getDeterminant())); } void moveOriginInDeviceSpace (Point delta) noexcept diff --git a/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp b/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp index 3913247b69..be79b6d41f 100644 --- a/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp +++ b/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp @@ -580,7 +580,7 @@ void Direct2DLowLevelGraphicsContext::addTransform (const AffineTransform& trans float Direct2DLowLevelGraphicsContext::getPhysicalPixelScaleFactor() { - return currentState->transform.getScaleFactor(); + return std::sqrt (std::abs (currentState->transform.getDeterminant())); } bool Direct2DLowLevelGraphicsContext::clipToRectangle (const Rectangle& r) diff --git a/modules/juce_gui_basics/components/juce_Component.cpp b/modules/juce_gui_basics/components/juce_Component.cpp index d7734de4d2..67d6445dec 100644 --- a/modules/juce_gui_basics/components/juce_Component.cpp +++ b/modules/juce_gui_basics/components/juce_Component.cpp @@ -1300,7 +1300,8 @@ float Component::getApproximateScaleFactorForComponent (Component* targetCompone transform = transform.scaled (target->getDesktopScaleFactor()); } - return (transform.getScaleFactor() / Desktop::getInstance().getGlobalScaleFactor()); + auto transformScale = std::sqrt (std::abs (transform.getDeterminant())); + return transformScale / Desktop::getInstance().getGlobalScaleFactor(); } //============================================================================== diff --git a/modules/juce_gui_basics/drawables/juce_SVGParser.cpp b/modules/juce_gui_basics/drawables/juce_SVGParser.cpp index 2d003e3565..cdaec0206e 100644 --- a/modules/juce_gui_basics/drawables/juce_SVGParser.cpp +++ b/modules/juce_gui_basics/drawables/juce_SVGParser.cpp @@ -1024,7 +1024,8 @@ private: float getStrokeWidth (const String& strokeWidth) const noexcept { - return transform.getScaleFactor() * getCoordLength (strokeWidth, viewBoxW); + auto transformScale = std::sqrt (std::abs (transform.getDeterminant())); + return transformScale * getCoordLength (strokeWidth, viewBoxW); } PathStrokeType getStrokeFor (const XmlPath& xml) const