Browse Source

Much faster software rendering of glyphs when display is scaled.

tags/2021-05-28
jules 12 years ago
parent
commit
48ae5d16a7
2 changed files with 65 additions and 55 deletions
  1. +1
    -1
      modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp
  2. +64
    -54
      modules/juce_graphics/native/juce_RenderingHelpers.h

+ 1
- 1
modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp View File

@@ -31,7 +31,7 @@ LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image&
LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image& image, Point<int> origin, LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image& image, Point<int> origin,
const RectangleList<int>& initialClip) const RectangleList<int>& initialClip)
: RenderingHelpers::StackBasedLowLevelGraphicsContext<RenderingHelpers::SoftwareRendererSavedState> : RenderingHelpers::StackBasedLowLevelGraphicsContext<RenderingHelpers::SoftwareRendererSavedState>
(new RenderingHelpers::SoftwareRendererSavedState (image, initialClip, origin.x, origin.y))
(new RenderingHelpers::SoftwareRendererSavedState (image, initialClip, origin))
{ {
} }


+ 64
- 54
modules/juce_graphics/native/juce_RenderingHelpers.h View File

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


Loading…
Cancel
Save