From 32c98223ac9be9329fdd471301df8a94a082b75f Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 30 Jul 2013 09:59:03 +0100 Subject: [PATCH] Refactored some lowlevelgraphicscontext classes to remove duplicated code. --- .../juce_core/threads/juce_WaitableEvent.h | 2 + .../juce_LowLevelGraphicsSoftwareRenderer.cpp | 118 +----------------- .../juce_LowLevelGraphicsSoftwareRenderer.h | 50 ++------ .../juce_graphics/geometry/juce_EdgeTable.cpp | 4 +- .../native/juce_RenderingHelpers.h | 83 ++++++++++++ .../opengl/juce_OpenGLGraphicsContext.cpp | 43 ++----- 6 files changed, 105 insertions(+), 195 deletions(-) diff --git a/modules/juce_core/threads/juce_WaitableEvent.h b/modules/juce_core/threads/juce_WaitableEvent.h index 47843b5022..f0f1ad1058 100644 --- a/modules/juce_core/threads/juce_WaitableEvent.h +++ b/modules/juce_core/threads/juce_WaitableEvent.h @@ -46,6 +46,8 @@ public: //============================================================================== /** Creates a WaitableEvent object. + The object is initially in an unsignalled state. + @param manualReset If this is false, the event will be reset automatically when the wait() method is called. If manualReset is true, then once the event is signalled, the only way to reset it will be by calling the reset() method. diff --git a/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp b/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp index 213f7def49..b2222b4b28 100644 --- a/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp +++ b/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp @@ -23,126 +23,16 @@ */ LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image& image) - : savedState (new RenderingHelpers::SoftwareRendererSavedState (image, image.getBounds())) + : RenderingHelpers::StackBasedLowLevelGraphicsContext + (new RenderingHelpers::SoftwareRendererSavedState (image, image.getBounds())) { } LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image& image, Point origin, const RectangleList& initialClip) - : savedState (new RenderingHelpers::SoftwareRendererSavedState (image, initialClip, origin.x, origin.y)) + : RenderingHelpers::StackBasedLowLevelGraphicsContext + (new RenderingHelpers::SoftwareRendererSavedState (image, initialClip, origin.x, origin.y)) { } LowLevelGraphicsSoftwareRenderer::~LowLevelGraphicsSoftwareRenderer() {} - -//============================================================================== -bool LowLevelGraphicsSoftwareRenderer::isVectorDevice() const { return false; } - -void LowLevelGraphicsSoftwareRenderer::setOrigin (int x, int y) { savedState->transform.setOrigin (x, y); } -void LowLevelGraphicsSoftwareRenderer::addTransform (const AffineTransform& t) { savedState->transform.addTransform (t); } -float LowLevelGraphicsSoftwareRenderer::getScaleFactor() { return savedState->transform.getScaleFactor(); } - -Rectangle LowLevelGraphicsSoftwareRenderer::getClipBounds() const { return savedState->getClipBounds(); } -bool LowLevelGraphicsSoftwareRenderer::isClipEmpty() const { return savedState->clip == nullptr; } - -bool LowLevelGraphicsSoftwareRenderer::clipToRectangle (const Rectangle& r) { return savedState->clipToRectangle (r); } -bool LowLevelGraphicsSoftwareRenderer::clipToRectangleList (const RectangleList& r) { return savedState->clipToRectangleList (r); } -void LowLevelGraphicsSoftwareRenderer::excludeClipRectangle (const Rectangle& r) { savedState->excludeClipRectangle (r); } - -void LowLevelGraphicsSoftwareRenderer::clipToPath (const Path& path, const AffineTransform& transform) -{ - savedState->clipToPath (path, transform); -} - -void LowLevelGraphicsSoftwareRenderer::clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform) -{ - savedState->clipToImageAlpha (sourceImage, transform); -} - -bool LowLevelGraphicsSoftwareRenderer::clipRegionIntersects (const Rectangle& r) -{ - return savedState->clipRegionIntersects (r); -} - -//============================================================================== -void LowLevelGraphicsSoftwareRenderer::saveState() { savedState.save(); } -void LowLevelGraphicsSoftwareRenderer::restoreState() { savedState.restore(); } - -void LowLevelGraphicsSoftwareRenderer::beginTransparencyLayer (float opacity) { savedState.beginTransparencyLayer (opacity); } -void LowLevelGraphicsSoftwareRenderer::endTransparencyLayer() { savedState.endTransparencyLayer(); } - -//============================================================================== -void LowLevelGraphicsSoftwareRenderer::setFill (const FillType& fillType) -{ - savedState->fillType = fillType; -} - -void LowLevelGraphicsSoftwareRenderer::setOpacity (float newOpacity) -{ - savedState->fillType.setOpacity (newOpacity); -} - -void LowLevelGraphicsSoftwareRenderer::setInterpolationQuality (Graphics::ResamplingQuality quality) -{ - savedState->interpolationQuality = quality; -} - -//============================================================================== -void LowLevelGraphicsSoftwareRenderer::fillRect (const Rectangle& r, const bool replaceExistingContents) -{ - savedState->fillRect (r, replaceExistingContents); -} - -void LowLevelGraphicsSoftwareRenderer::fillPath (const Path& path, const AffineTransform& transform) -{ - savedState->fillPath (path, transform); -} - -void LowLevelGraphicsSoftwareRenderer::drawImage (const Image& sourceImage, const AffineTransform& transform) -{ - savedState->renderImage (sourceImage, transform, nullptr); -} - -void LowLevelGraphicsSoftwareRenderer::drawLine (const Line & line) -{ - Path p; - p.addLineSegment (line, 1.0f); - fillPath (p, AffineTransform::identity); -} - -void LowLevelGraphicsSoftwareRenderer::drawVerticalLine (const int x, const float top, const float bottom) -{ - if (bottom > top) - savedState->fillRect (Rectangle ((float) x, top, 1.0f, bottom - top)); -} - -void LowLevelGraphicsSoftwareRenderer::drawHorizontalLine (const int y, const float left, const float right) -{ - if (right > left) - savedState->fillRect (Rectangle (left, (float) y, right - left, 1.0f)); -} - -void LowLevelGraphicsSoftwareRenderer::drawGlyph (int glyphNumber, const AffineTransform& transform) -{ - const Font& f = savedState->font; - - if (transform.isOnlyTranslation() && savedState->transform.isOnlyTranslated) - { - using namespace RenderingHelpers; - - GlyphCache , SoftwareRendererSavedState>::getInstance() - .drawGlyph (*savedState, f, glyphNumber, - transform.getTranslationX(), - transform.getTranslationY()); - } - else - { - const float fontHeight = f.getHeight(); - savedState->drawGlyph (f, glyphNumber, - AffineTransform::scale (fontHeight * f.getHorizontalScale(), fontHeight) - .followedBy (transform)); - } -} - -void LowLevelGraphicsSoftwareRenderer::setFont (const Font& newFont) { savedState->font = newFont; } -const Font& LowLevelGraphicsSoftwareRenderer::getFont() { return savedState->font; } diff --git a/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h b/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h index c6424b6c49..b05aba719b 100644 --- a/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h +++ b/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h @@ -36,57 +36,21 @@ User code is not supposed to create instances of this class directly - do all your rendering via the Graphics class instead. */ -class JUCE_API LowLevelGraphicsSoftwareRenderer : public LowLevelGraphicsContext +class JUCE_API LowLevelGraphicsSoftwareRenderer : public RenderingHelpers::StackBasedLowLevelGraphicsContext { public: //============================================================================== + /** Creates a context to render into an image. */ LowLevelGraphicsSoftwareRenderer (const Image& imageToRenderOnto); + + /** Creates a context to render into a clipped subsection of an image. */ LowLevelGraphicsSoftwareRenderer (const Image& imageToRenderOnto, Point origin, const RectangleList& initialClip); + + /** Destructor. */ ~LowLevelGraphicsSoftwareRenderer(); - bool isVectorDevice() const override; - void setOrigin (int x, int y) override; - void addTransform (const AffineTransform&) override; - float getScaleFactor() override; - bool clipToRectangle (const Rectangle&) override; - bool clipToRectangleList (const RectangleList&) override; - void excludeClipRectangle (const Rectangle&) override; - void clipToPath (const Path&, const AffineTransform&) override; - void clipToImageAlpha (const Image&, const AffineTransform&) override; - bool clipRegionIntersects (const Rectangle&) override; - Rectangle getClipBounds() const override; - bool isClipEmpty() const override; - - void saveState() override; - void restoreState() override; - - void beginTransparencyLayer (float opacity) override; - void endTransparencyLayer() override; - - void setFill (const FillType&) override; - void setOpacity (float opacity) override; - void setInterpolationQuality (Graphics::ResamplingQuality) override; - - void fillRect (const Rectangle&, bool replaceExistingContents) override; - void fillPath (const Path&, const AffineTransform&) override; - - void drawImage (const Image&, const AffineTransform&) override; - - void drawLine (const Line &) override; - void drawVerticalLine (int x, float top, float bottom) override; - void drawHorizontalLine (int x, float top, float bottom) override; - - void setFont (const Font&) override; - const Font& getFont() override; - void drawGlyph (int glyphNumber, const AffineTransform&) override; - - const Image& getImage() const noexcept { return savedState->image; } - const RenderingHelpers::TranslationOrTransform& getTransform() const noexcept { return savedState->transform; } - -protected: - RenderingHelpers::SavedStateStack savedState; - +private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LowLevelGraphicsSoftwareRenderer) }; diff --git a/modules/juce_graphics/geometry/juce_EdgeTable.cpp b/modules/juce_graphics/geometry/juce_EdgeTable.cpp index 5ed84796ff..7a3110acdd 100644 --- a/modules/juce_graphics/geometry/juce_EdgeTable.cpp +++ b/modules/juce_graphics/geometry/juce_EdgeTable.cpp @@ -25,9 +25,9 @@ const int juce_edgeTableDefaultEdgesPerLine = 32; //============================================================================== -EdgeTable::EdgeTable (const Rectangle& bounds_, +EdgeTable::EdgeTable (const Rectangle& area, const Path& path, const AffineTransform& transform) - : bounds (bounds_), + : bounds (area), maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), needToCheckEmptinesss (true) diff --git a/modules/juce_graphics/native/juce_RenderingHelpers.h b/modules/juce_graphics/native/juce_RenderingHelpers.h index a57745c5fd..c69124a8a0 100644 --- a/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -2216,6 +2216,11 @@ public: } //============================================================================== + void setFillType (const FillType& newFill) + { + fillType = newFill; + } + void fillTargetRect (const Rectangle& r, const bool replaceContents) { if (fillType.isColour()) @@ -2301,6 +2306,24 @@ public: } } + void drawGlyph (int glyphNumber, const AffineTransform& trans) + { + if (trans.isOnlyTranslation() && transform.isOnlyTranslated) + { + GlyphCache , SoftwareRendererSavedState>::getInstance() + .drawGlyph (*this, font, glyphNumber, + trans.getTranslationX(), + trans.getTranslationY()); + } + else + { + const float fontHeight = font.getHeight(); + drawGlyph (font, glyphNumber, + AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight) + .followedBy (trans)); + } + } + void drawGlyph (const Font& f, int glyphNumber, const AffineTransform& t) { if (clip != nullptr) @@ -2353,7 +2376,19 @@ public: } } + void drawLine (const Line & line) + { + Path p; + p.addLineSegment (line, 1.0f); + fillPath (p, AffineTransform::identity); + } + //============================================================================== + void drawImage (const Image& sourceImage, const AffineTransform& trans) + { + renderImage (sourceImage, trans, nullptr); + } + void renderImage (const Image& sourceImage, const AffineTransform& trans, const ClipRegions::Base* const tiledFillClipRegion) { @@ -2445,6 +2480,13 @@ public: : currentState (initialState) {} + SavedStateStack() noexcept {} + + void initialise (StateObjectType* state) + { + currentState = state; + } + inline StateObjectType* operator->() const noexcept { return currentState; } inline StateObjectType& operator*() const noexcept { return *currentState; } @@ -2486,6 +2528,47 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SavedStateStack) }; +//============================================================================== +template +class StackBasedLowLevelGraphicsContext : public LowLevelGraphicsContext +{ +public: + bool isVectorDevice() const override { return false; } + void setOrigin (int x, int y) override { stack->transform.setOrigin (x, y); } + void addTransform (const AffineTransform& t) override { stack->transform.addTransform (t); } + float getScaleFactor() override { return stack->transform.getScaleFactor(); } + 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); } + bool clipToRectangle (const Rectangle& r) override { return stack->clipToRectangle (r); } + bool clipToRectangleList (const RectangleList& r) override { return stack->clipToRectangleList (r); } + void excludeClipRectangle (const Rectangle& r) override { stack->excludeClipRectangle (r); } + void clipToPath (const Path& path, const AffineTransform& t) override { stack->clipToPath (path, t); } + void clipToImageAlpha (const Image& im, const AffineTransform& t) override { stack->clipToImageAlpha (im, t); } + void saveState() override { stack.save(); } + void restoreState() override { stack.restore(); } + void beginTransparencyLayer (float opacity) override { stack.beginTransparencyLayer (opacity); } + void endTransparencyLayer() override { stack.endTransparencyLayer(); } + void setFill (const FillType& fillType) override { stack->setFillType (fillType); } + void setOpacity (float newOpacity) override { stack->fillType.setOpacity (newOpacity); } + void setInterpolationQuality (Graphics::ResamplingQuality quality) override { stack->interpolationQuality = quality; } + void fillRect (const Rectangle& r, bool replace) override { stack->fillRect (r, replace); } + void fillPath (const Path& path, const AffineTransform& t) override { stack->fillPath (path, t); } + void drawImage (const Image& im, const AffineTransform& t) override { stack->drawImage (im, t); } + void drawVerticalLine (int x, float top, float bottom) override { if (top < bottom) stack->fillRect (Rectangle ((float) x, top, 1.0f, bottom - top)); } + void drawHorizontalLine (int y, float left, float right) override { if (left < right) stack->fillRect (Rectangle (left, (float) y, right - left, 1.0f)); } + void drawGlyph (int glyphNumber, const AffineTransform& t) override { stack->drawGlyph (glyphNumber, t); } + void drawLine (const Line & line) override { stack->drawLine (line); } + void setFont (const Font& newFont) override { stack->font = newFont; } + const Font& getFont() override { return stack->font; } + +protected: + StackBasedLowLevelGraphicsContext (SavedStateType* initialState) : stack (initialState) {} + StackBasedLowLevelGraphicsContext() {} + + RenderingHelpers::SavedStateStack stack; +}; + } #if JUCE_MSVC diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp index af78f7dd3c..dc069caad0 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp @@ -2109,45 +2109,16 @@ private: }; //============================================================================== -class ShaderContext : public LowLevelGraphicsContext +class ShaderContext : public RenderingHelpers::StackBasedLowLevelGraphicsContext { public: - ShaderContext (const Target& target) - : glState (target), stack (new SavedState (&glState)) - {} - - bool isVectorDevice() const { return false; } - void setOrigin (int x, int y) { stack->transform.setOrigin (x, y); } - void addTransform (const AffineTransform& t) { stack->transform.addTransform (t); } - float getScaleFactor() { return stack->transform.getScaleFactor(); } - Rectangle getClipBounds() const { return stack->getClipBounds(); } - bool isClipEmpty() const { return stack->clip == nullptr; } - bool clipRegionIntersects (const Rectangle& r) { return stack->clipRegionIntersects (r); } - bool clipToRectangle (const Rectangle& r) { return stack->clipToRectangle (r); } - bool clipToRectangleList (const RectangleList& r) { return stack->clipToRectangleList (r); } - void excludeClipRectangle (const Rectangle& r) { stack->excludeClipRectangle (r); } - void clipToPath (const Path& path, const AffineTransform& t) { stack->clipToPath (path, t); } - void clipToImageAlpha (const Image& im, const AffineTransform& t) { stack->clipToImageAlpha (im, t); } - void saveState() { stack.save(); } - void restoreState() { stack.restore(); } - void beginTransparencyLayer (float opacity) { stack.beginTransparencyLayer (opacity); } - void endTransparencyLayer() { stack.endTransparencyLayer(); } - void setFill (const FillType& fillType) { stack->setFillType (fillType); } - void setOpacity (float newOpacity) { stack->fillType.setOpacity (newOpacity); } - void setInterpolationQuality (Graphics::ResamplingQuality quality) { stack->interpolationQuality = quality; } - void fillRect (const Rectangle& r, bool replace) { stack->fillRect (r, replace); } - void fillPath (const Path& path, const AffineTransform& t) { stack->fillPath (path, t); } - void drawImage (const Image& im, const AffineTransform& t) { stack->drawImage (im, t); } - void drawVerticalLine (int x, float top, float bottom) { if (top < bottom) stack->fillRect (Rectangle ((float) x, top, 1.0f, bottom - top)); } - void drawHorizontalLine (int y, float left, float right) { if (left < right) stack->fillRect (Rectangle (left, (float) y, right - left, 1.0f)); } - void drawGlyph (int glyphNumber, const AffineTransform& t) { stack->drawGlyph (glyphNumber, t); } - void drawLine (const Line & line) { stack->drawLine (line); } - void setFont (const Font& newFont) { stack->font = newFont; } - const Font& getFont() { return stack->font; } + ShaderContext (const Target& target) : glState (target) + { + stack.initialise (new SavedState (&glState)); + } private: GLState glState; - RenderingHelpers::SavedStateStack stack; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ShaderContext) }; @@ -2157,8 +2128,8 @@ private: class NonShaderContext : public LowLevelGraphicsSoftwareRenderer { public: - NonShaderContext (const Target& target_, const Image& image_) - : LowLevelGraphicsSoftwareRenderer (image_), target (target_), image (image_) + NonShaderContext (const Target& t, const Image& im) + : LowLevelGraphicsSoftwareRenderer (im), target (t), image (im) {} ~NonShaderContext()