Hi,
If you enable the built in buffering with `setBufferedToImage(true)’ it will make a backing cache and work, but the imagery will be upscaled on retina so that it looks chunky and blurred. However, you can try this to see what kind of performance change you might expect.
If this is an advantage, then you can fix the caching retina (and non-retina) as follows:
- determine the display scale (eg retina = 2, everything else = 1)
const Desktop::Displays::Display& dis =
Desktop::getInstance().getDisplays().getMainDisplay();
int displayScale = (int)dis.scale;
- use a custom scaling cache in your drawing component (see below implementation)
setCachedComponentImage(new ScalingCachedComponentImage(*this,
displayScale));
- in your component, work in “real” coordinates. For example, in my
paint' method i call a local
_getLocalBounds’ method and use the bounds from this to issue my drawing commands. i do NOT call getWidth() or getHeight() independently, these will be the wrong size. the purpose of this is because the painting here winds up on the cached image and therefore must be the appropriate pixel size.
[code]template Rectangle scaledUp(const Rectangle& r, int s)
{
return Rectangle(r.getX()*s, r.getY()*s,
r.getWidth()*s, r.getHeight()*s);
}
Rectangle MyComponent:_getLocalBounds() const
{
Rectangle b = getLocalBounds();
b = scaledUp(b, displayScale);
return b;
}
[/code]
- implement the ScalingCachedComponent. Here’s my version,
[code]/**
- Copyright © 2012 Voidware Ltd.
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the “Software”), to
- deal in the Software without restriction, including without limitation the
- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- sell copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED “AS IS,” WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- IN THE SOFTWARE.
*/
#ifndef cci_h
#define cci_h
#include “…/JuceLibraryCode/JuceHeader.h”
#include “utils.h”
/* Replacement for the standard cached image that makes use of the UI
- scale factor to support `retina’ style coordinate spaces.
*/
class ScalingCachedComponentImage: public CachedComponentImage
{
public:
ScalingCachedComponentImage (Component& owner_, int scale) noexcept
: owner (owner_), _scale(scale) {}
void paint (Graphics& g)
{
Rectangle<int> bounds (scaledUp(owner.getLocalBounds(), _scale));
if (image.isNull() || image.getBounds() != bounds)
{
image = Image (owner.isOpaque() ? Image::RGB : Image::ARGB,
jmax (1, bounds.getWidth()), jmax (1, bounds.getHeight()), ! owner.isOpaque());
validArea.clear();
}
Graphics imG (image);
LowLevelGraphicsContext* const lg = imG.getInternalContext();
for (RectangleList::Iterator i (validArea); i.next();)
lg->excludeClipRectangle (*i.getRectangle());
if (! lg->isClipEmpty())
{
if (! owner.isOpaque())
{
lg->setFill (Colours::transparentBlack);
lg->fillRect (bounds, true);
lg->setFill (Colours::black);
}
owner.paintEntireComponent (imG, true);
}
validArea = bounds;
g.setColour (Colours::black.withAlpha (owner.getAlpha()));
// draw the image applying the display scale downscaling.
// this downscale wont actually be performed but indicates to
// iOS that it can use the image at pixel level
int w = image.getWidth();
int h = image.getHeight();
g.drawImage(image,
0, 0,
w/_scale, h/_scale,
0, 0,
w, h,
false);
}
void invalidateAll() { validArea.clear(); }
void invalidate (const Rectangle<int>& area) { validArea.subtract (area); }
void releaseResources() { image = Image::null; }
private:
Image image;
RectangleList validArea;
Component& owner;
int _scale;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ScalingCachedComponentImage);
};
#endif // cci_h
[/code]
good luck!
– hugh.