From ca3bc70acdf82afb4a1ad759d411e5da59342793 Mon Sep 17 00:00:00 2001 From: jules Date: Mon, 19 Aug 2013 19:17:59 +0100 Subject: [PATCH] Changes to improve scaling when using cached component images and component effects. --- .../contexts/juce_GraphicsContext.cpp | 2 +- .../contexts/juce_LowLevelGraphicsContext.h | 3 +- ...uce_LowLevelGraphicsPostScriptRenderer.cpp | 3 +- .../juce_LowLevelGraphicsPostScriptRenderer.h | 3 +- .../native/juce_RenderingHelpers.h | 22 ++++++------- .../native/juce_mac_CoreGraphicsContext.h | 3 +- .../native/juce_mac_CoreGraphicsContext.mm | 20 ++++++++---- .../juce_win32_Direct2DGraphicsContext.cpp | 2 +- .../components/juce_Component.cpp | 32 ++++++++++++------- 9 files changed, 50 insertions(+), 40 deletions(-) diff --git a/modules/juce_graphics/contexts/juce_GraphicsContext.cpp b/modules/juce_graphics/contexts/juce_GraphicsContext.cpp index 9c3d248bcd..4ddc765d18 100644 --- a/modules/juce_graphics/contexts/juce_GraphicsContext.cpp +++ b/modules/juce_graphics/contexts/juce_GraphicsContext.cpp @@ -384,7 +384,7 @@ void Graphics::strokePath (const Path& path, const AffineTransform& transform) const { Path stroke; - strokeType.createStrokedPath (stroke, path, transform, context.getScaleFactor()); + strokeType.createStrokedPath (stroke, path, transform, context.getPhysicalPixelScaleFactor()); fillPath (stroke); } diff --git a/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h b/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h index 92298fa789..183318073e 100644 --- a/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h +++ b/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h @@ -66,8 +66,7 @@ public: */ virtual void setOrigin (int x, int y) = 0; virtual void addTransform (const AffineTransform&) = 0; - virtual float getScaleFactor() = 0; - virtual float getTargetDeviceScaleFactor() = 0; + virtual float getPhysicalPixelScaleFactor() = 0; virtual bool clipToRectangle (const Rectangle&) = 0; virtual bool clipToRectangleList (const RectangleList&) = 0; diff --git a/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp b/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp index bd04f52cac..48ffbe3890 100644 --- a/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp +++ b/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp @@ -105,8 +105,7 @@ void LowLevelGraphicsPostScriptRenderer::addTransform (const AffineTransform& /* jassertfalse; } -float LowLevelGraphicsPostScriptRenderer::getScaleFactor() { return 1.0f; } -float LowLevelGraphicsPostScriptRenderer::getTargetDeviceScaleFactor() { return 1.0f; } +float LowLevelGraphicsPostScriptRenderer::getPhysicalPixelScaleFactor() { return 1.0f; } bool LowLevelGraphicsPostScriptRenderer::clipToRectangle (const Rectangle& r) { diff --git a/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h b/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h index 3c6d8b0eab..ba11805889 100644 --- a/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h +++ b/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h @@ -49,8 +49,7 @@ public: bool isVectorDevice() const override; void setOrigin (int x, int y) override; void addTransform (const AffineTransform&) override; - float getScaleFactor() override; - float getTargetDeviceScaleFactor() override; + float getPhysicalPixelScaleFactor() override; bool clipToRectangle (const Rectangle&) override; bool clipToRectangleList (const RectangleList&) override; diff --git a/modules/juce_graphics/native/juce_RenderingHelpers.h b/modules/juce_graphics/native/juce_RenderingHelpers.h index 94e42f71f1..4bc58f171d 100644 --- a/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -86,12 +86,9 @@ public: } } - float getScaleFactor() const noexcept + float getPhysicalPixelScaleFactor() const noexcept { - return isOnlyTranslated ? 1.0f - : (isRotated ? complexTransform.getScaleFactor() - : jmax (complexTransform.mat00, - complexTransform.mat11)); + return isOnlyTranslated ? 1.0f : complexTransform.getScaleFactor(); } void moveOriginInDeviceSpace (Point delta) noexcept @@ -2182,15 +2179,17 @@ public: if (clip != nullptr) { if (transform.isOnlyTranslated) + { fillTargetRect (transform.translated (r), replaceContents); + } + else if (! transform.isRotated) + { + fillTargetRect (transform.transformed (r), replaceContents); + } else { jassert (! replaceContents); // not implemented.. - - if (! transform.isRotated) - fillTargetRect (transform.transformed (r.toFloat())); - else - fillRectAsPath (r); + fillRectAsPath (r); } } } @@ -2566,8 +2565,7 @@ public: bool isVectorDevice() const override { return false; } void setOrigin (int x, int y) override { stack->transform.setOrigin (Point (x, y)); } void addTransform (const AffineTransform& t) override { stack->transform.addTransform (t); } - float getScaleFactor() override { return stack->transform.getScaleFactor(); } - float getTargetDeviceScaleFactor() override { return stack->transform.getScaleFactor(); } + float getPhysicalPixelScaleFactor() override { return stack->transform.getPhysicalPixelScaleFactor(); } Rectangle getClipBounds() const override { return stack->getClipBounds(); } bool isClipEmpty() const override { return stack->clip == nullptr; } bool clipRegionIntersects (const Rectangle& r) override { return stack->clipRegionIntersects (r); } diff --git a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h index e6e5725848..f791f6548c 100644 --- a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h +++ b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h @@ -37,8 +37,7 @@ public: void setOrigin (int x, int y) override; void addTransform (const AffineTransform&) override; - float getScaleFactor() override; - float getTargetDeviceScaleFactor() override { return targetScale; } + float getPhysicalPixelScaleFactor() override; bool clipToRectangle (const Rectangle&) override; bool clipToRectangleList (const RectangleList&) override; void excludeClipRectangle (const Rectangle&) override; diff --git a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm index 6d06842113..d878dd00c3 100644 --- a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm +++ b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm @@ -123,10 +123,10 @@ ImagePixelData::Ptr NativeImageType::create (Image::PixelFormat format, int widt } //============================================================================== -CoreGraphicsContext::CoreGraphicsContext (CGContextRef context_, const float flipHeight_, const float targetScale_) - : context (context_), - flipHeight (flipHeight_), - targetScale (targetScale_), +CoreGraphicsContext::CoreGraphicsContext (CGContextRef c, const float h, const float scale) + : context (c), + flipHeight (h), + targetScale (scale), lastClipRectIsValid (false), state (new SavedState()) { @@ -167,12 +167,18 @@ void CoreGraphicsContext::addTransform (const AffineTransform& transform) .translated (0, -flipHeight) .scaled (1.0f, -1.0f)); lastClipRectIsValid = false; + + jassert (getPhysicalPixelScaleFactor() > 0.0f); + jassert (getPhysicalPixelScaleFactor() > 0.0f); } -float CoreGraphicsContext::getScaleFactor() +float CoreGraphicsContext::getPhysicalPixelScaleFactor() { - CGAffineTransform t = CGContextGetCTM (context); - return (float) juce_hypot (t.a + t.c, t.b + t.d); + const CGAffineTransform t = CGContextGetCTM (context); + + return targetScale * (float) (juce_hypot (t.a, t.c) + juce_hypot (t.b, t.d)) / 2.0f; + +// return targetScale * (float) (t.a + t.d) / 2.0f; } bool CoreGraphicsContext::clipToRectangle (const Rectangle& r) diff --git a/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp b/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp index 9900825b02..e0855a979a 100644 --- a/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp +++ b/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp @@ -92,7 +92,7 @@ public: currentState->transform = transform.followedBy (currentState->transform); } - float getScaleFactor() + float getPhysicalPixelScaleFactor() { return currentState->transform.getScaleFactor(); } diff --git a/modules/juce_gui_basics/components/juce_Component.cpp b/modules/juce_gui_basics/components/juce_Component.cpp index 52bd47a4cc..1cfb1985ff 100644 --- a/modules/juce_gui_basics/components/juce_Component.cpp +++ b/modules/juce_gui_basics/components/juce_Component.cpp @@ -721,16 +721,21 @@ bool Component::isOpaque() const noexcept class StandardCachedComponentImage : public CachedComponentImage { public: - StandardCachedComponentImage (Component& c) noexcept : owner (c) {} + StandardCachedComponentImage (Component& c) noexcept : owner (c), scale (1.0f) {} void paint (Graphics& g) override { - const Rectangle bounds (owner.getLocalBounds()); + scale = g.getInternalContext().getPhysicalPixelScaleFactor(); + const Rectangle compBounds (owner.getLocalBounds()); + const Rectangle imageBounds (compBounds * scale); - if (image.isNull() || image.getBounds() != bounds) + if (image.isNull() || image.getBounds() != imageBounds) { - image = Image (owner.isOpaque() ? Image::RGB : Image::ARGB, - jmax (1, bounds.getWidth()), jmax (1, bounds.getHeight()), ! owner.isOpaque()); + image = Image (owner.isOpaque() ? Image::RGB + : Image::ARGB, + jmax (1, imageBounds.getWidth()), + jmax (1, imageBounds.getHeight()), + ! owner.isOpaque()); validArea.clear(); } @@ -747,28 +752,31 @@ public: if (! owner.isOpaque()) { lg.setFill (Colours::transparentBlack); - lg.fillRect (bounds, true); + lg.fillRect (imageBounds, true); lg.setFill (Colours::black); } + lg.addTransform (AffineTransform::scale (scale)); owner.paintEntireComponent (imG, true); } } - validArea = bounds; + validArea = imageBounds; g.setColour (Colours::black.withAlpha (owner.getAlpha())); - g.drawImageAt (image, 0, 0); + g.drawImage (image, 0, 0, compBounds.getWidth(), compBounds.getHeight(), + 0, 0, imageBounds.getWidth(), imageBounds.getHeight(), false); } bool invalidateAll() override { validArea.clear(); return true; } - bool invalidate (const Rectangle& area) override { validArea.subtract (area); return true; } + bool invalidate (const Rectangle& area) override { validArea.subtract (area * scale); return true; } void releaseResources() override { image = Image::null; } private: Image image; RectangleList validArea; Component& owner; + float scale; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StandardCachedComponentImage) }; @@ -1936,10 +1944,12 @@ void Component::paintEntireComponent (Graphics& g, const bool ignoreAlphaLevel) if (effect != nullptr) { - const float scale = g.getInternalContext().getTargetDeviceScaleFactor(); + const float scale = g.getInternalContext().getPhysicalPixelScaleFactor(); + + const Rectangle bounds (getLocalBounds() * scale); Image effectImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, - (int) (scale * getWidth()), (int) (scale * getHeight()), ! flags.opaqueFlag); + bounds.getWidth(), bounds.getHeight(), ! flags.opaqueFlag); { Graphics g2 (effectImage); g2.addTransform (AffineTransform::scale (scale));