diff --git a/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp b/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp index b2222b4b28..a57e4d62d7 100644 --- a/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp +++ b/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp @@ -31,7 +31,7 @@ LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image& LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image& image, Point origin, const RectangleList& initialClip) : RenderingHelpers::StackBasedLowLevelGraphicsContext - (new RenderingHelpers::SoftwareRendererSavedState (image, initialClip, origin.x, origin.y)) + (new RenderingHelpers::SoftwareRendererSavedState (image, initialClip, origin)) { } diff --git a/modules/juce_graphics/native/juce_RenderingHelpers.h b/modules/juce_graphics/native/juce_RenderingHelpers.h index 9939a58d5b..94e42f71f1 100644 --- a/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -39,50 +39,44 @@ namespace RenderingHelpers class TranslationOrTransform { public: - TranslationOrTransform (int x, int y) noexcept - : xOffset (x), yOffset (y), isOnlyTranslated (true), isRotated (false) + TranslationOrTransform (Point origin) noexcept + : offset (origin), isOnlyTranslated (true), isRotated (false) { } TranslationOrTransform (const TranslationOrTransform& other) noexcept - : complexTransform (other.complexTransform), - xOffset (other.xOffset), yOffset (other.yOffset), + : complexTransform (other.complexTransform), offset (other.offset), isOnlyTranslated (other.isOnlyTranslated), isRotated (other.isRotated) { } AffineTransform getTransform() const noexcept { - return isOnlyTranslated ? AffineTransform::translation ((float) xOffset, (float) yOffset) + return isOnlyTranslated ? AffineTransform::translation ((float) offset.x, (float) offset.y) : complexTransform; } AffineTransform getTransformWith (const AffineTransform& userTransform) const noexcept { - return isOnlyTranslated ? userTransform.translated ((float) xOffset, (float) yOffset) + return isOnlyTranslated ? userTransform.translated ((float) offset.x, (float) offset.y) : userTransform.followedBy (complexTransform); } - void setOrigin (const int x, const int y) noexcept + void setOrigin (Point delta) noexcept { if (isOnlyTranslated) - { - xOffset += x; - yOffset += y; - } + offset += delta; else - { - complexTransform = AffineTransform::translation ((float) x, (float) y) + complexTransform = AffineTransform::translation ((float) delta.x, (float) delta.y) .followedBy (complexTransform); - } } void addTransform (const AffineTransform& t) noexcept { if (isOnlyTranslated && t.isOnlyTranslation()) { - xOffset += (int) t.getTranslationX(); - yOffset += (int) t.getTranslationY(); + offset += Point ((int) t.getTranslationX(), + (int) t.getTranslationY()); } else { @@ -100,42 +94,42 @@ public: complexTransform.mat11)); } - void moveOriginInDeviceSpace (const int dx, const int dy) noexcept + void moveOriginInDeviceSpace (Point delta) noexcept { if (isOnlyTranslated) - { - xOffset += dx; - yOffset += dy; - } + offset += delta; else - { - complexTransform = complexTransform.translated ((float) dx, (float) dy); - } + complexTransform = complexTransform.translated ((float) delta.x, (float) delta.y); } - template - Rectangle translated (const Rectangle& r) const noexcept + Rectangle translated (const Rectangle& r) const noexcept { jassert (isOnlyTranslated); - return r.translated (static_cast (xOffset), - static_cast (yOffset)); + return r + offset; } - template - Rectangle transformed (const Rectangle& r) const noexcept + Rectangle translated (const Rectangle& r) const noexcept + { + jassert (isOnlyTranslated); + return r + offset.toFloat(); + } + + template + RectangleOrPoint transformed (const RectangleOrPoint& r) const noexcept { + jassert (! isOnlyTranslated); return r.transformedBy (complexTransform); } template Rectangle deviceSpaceToUserSpace (const Rectangle& r) const noexcept { - return isOnlyTranslated ? r.translated (-xOffset, -yOffset) + return isOnlyTranslated ? r - offset : r.transformedBy (complexTransform.inverted()); } AffineTransform complexTransform; - int xOffset, yOffset; + Point offset; bool isOnlyTranslated, isRotated; }; @@ -166,7 +160,7 @@ public: } //============================================================================== - void drawGlyph (RenderTargetType& target, const Font& font, const int glyphNumber, float x, float y) + void drawGlyph (RenderTargetType& target, const Font& font, const int glyphNumber, Point pos) { ++accessCounter; CachedGlyphType* glyph = nullptr; @@ -209,7 +203,7 @@ public: } glyph->lastAccessCount = accessCounter.value; - glyph->draw (target, x, y); + glyph->draw (target, pos); } private: @@ -260,13 +254,13 @@ class CachedGlyphEdgeTable public: CachedGlyphEdgeTable() : glyph (0), lastAccessCount (0) {} - void draw (RendererType& state, float x, const float y) const + void draw (RendererType& state, Point pos) const { if (snapToIntegerCoordinate) - x = std::floor (x + 0.5f); + pos.x = std::floor (pos.x + 0.5f); if (edgeTable != nullptr) - state.fillEdgeTable (*edgeTable, x, roundToInt (y)); + state.fillEdgeTable (*edgeTable, pos.x, roundToInt (pos.y)); } void generate (const Font& newFont, const int glyphNumber) @@ -1981,13 +1975,13 @@ public: typedef typename ClipRegions::RectangleListRegion RectangleListRegionType; SavedStateBase (const Rectangle& initialClip) - : clip (new RectangleListRegionType (initialClip)), transform (0, 0), + : clip (new RectangleListRegionType (initialClip)), transform (Point()), interpolationQuality (Graphics::mediumResamplingQuality), transparencyLayerAlpha (1.0f) { } - SavedStateBase (const RectangleList& clipList, int x, int y) - : clip (new RectangleListRegionType (clipList)), transform (x, y), + SavedStateBase (const RectangleList& clipList, Point origin) + : clip (new RectangleListRegionType (clipList)), transform (origin), interpolationQuality (Graphics::mediumResamplingQuality), transparencyLayerAlpha (1.0f) { } @@ -2034,7 +2028,7 @@ public: { cloneClipIfMultiplyReferenced(); RectangleList offsetList (r); - offsetList.offsetAll (transform.xOffset, transform.yOffset); + offsetList.offsetAll (transform.offset.x, transform.offset.y); clip = clip->clipToRectangleList (offsetList); } else if (! transform.isRotated) @@ -2222,13 +2216,10 @@ public: void fillEdgeTable (const EdgeTable& edgeTable, const float x, const int y) { - jassert (transform.isOnlyTranslated); - if (clip != nullptr) { EdgeTableRegionType* edgeTableClip = new EdgeTableRegionType (edgeTable); - edgeTableClip->edgeTable.translate (x + transform.xOffset, - y + transform.yOffset); + edgeTableClip->edgeTable.translate (x, y); fillShape (edgeTableClip, false); } } @@ -2365,8 +2356,8 @@ public: { } - SoftwareRendererSavedState (const Image& im, const RectangleList& clipList, int x, int y) - : BaseClass (clipList, x, y), image (im) + SoftwareRendererSavedState (const Image& im, const RectangleList& clipList, Point origin) + : BaseClass (clipList, origin), image (im) { } @@ -2385,7 +2376,7 @@ public: s->image = Image (Image::ARGB, layerBounds.getWidth(), layerBounds.getHeight(), true); s->transparencyLayerAlpha = opacity; - s->transform.moveOriginInDeviceSpace (-layerBounds.getX(), -layerBounds.getY()); + s->transform.moveOriginInDeviceSpace (-layerBounds.getPosition()); s->cloneClipIfMultiplyReferenced(); s->clip->translate (-layerBounds.getPosition()); @@ -2412,12 +2403,31 @@ public: { if (clip != nullptr) { - if (trans.isOnlyTranslation() && transform.isOnlyTranslated) + if (trans.isOnlyTranslation() && ! transform.isRotated) { - GlyphCache , SoftwareRendererSavedState>::getInstance() - .drawGlyph (*this, font, glyphNumber, - trans.getTranslationX(), - trans.getTranslationY()); + typedef GlyphCache , SoftwareRendererSavedState> GlyphCacheType; + + GlyphCacheType& cache = GlyphCacheType::getInstance(); + + Point pos (trans.getTranslationX(), trans.getTranslationY()); + + if (transform.isOnlyTranslated) + { + cache.drawGlyph (*this, font, glyphNumber, pos + transform.offset.toFloat()); + } + else + { + pos = transform.transformed (pos); + + Font f (font); + f.setHeight (font.getHeight() * transform.complexTransform.mat11); + + const float xScale = transform.complexTransform.mat00 / transform.complexTransform.mat11; + if (std::abs (xScale - 1.0f) > 0.01f) + f.setHorizontalScale (xScale); + + cache.drawGlyph (*this, f, glyphNumber, pos); + } } else { @@ -2554,7 +2564,7 @@ class StackBasedLowLevelGraphicsContext : public LowLevelGraphicsContext { public: bool isVectorDevice() const override { return false; } - void setOrigin (int x, int y) override { stack->transform.setOrigin (x, y); } + 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(); }