Speeding Up Cocoa drawing?

This is from the SimDesignerCanvas thread:

[quote=91052:@Christoph De Vocht]I found a way to speedup the Canvas paint event A LOT ! In my experience this multiplies with at least 3 times the drawing speed.
Put this in the paint event (all credits to Sam for this !!)

declare sub CGContextSaveGState lib “Cocoa” ( context as integer )
declare sub CGContextSetInterpolationQuality lib “Cocoa” ( context as integer, quality as integer )
declare Sub CGContextRestoreGState lib “Cocoa” ( context as integer )
Dim CGContextRef as integer = g.handle( g.HandleTypeCGContextRef )

CGContextSaveGState CGContextRef
CGContextSetInterpolationQuality CGContextRef, 1

// ---------------------- Do drawing stuff here

// ---------------------- Finished, then restore the previous state.
CGContextRestoreGState CGContextRef[/quote]

I am ignorant in this area … but when something seems to good to be true, then it’s time to ask questions before charging ahead.

Is this generally applicable to all graphics objects or just graphic objects in all paint events in all controls (say a listbox).

Is there any downside to using this? If not why is this not part of the Xojo framework?

What if one uses it with a graphics object from a clipped region? What if one creates a clipped graphics object on a graphics object AFTER one has done this to it?

What about with the graphics object from a picture?

  • Karen

All that does is reduce the quality of images that are drawn to the Canvas - reduced quality means better performance. It should have no effect on lines, rectangles, fills, text, etc. that are drawn.

CGContextSetShouldAntialias should help.

PS: I think I have all those functions also in CGContextMBS plugin class if you guys use plugins.

This is controlled by the Graphics.AntiAlias property, so there’s no need to use declares here.

Actually that is only partially true…

DrawPicture for example does not honor this… which is why I had to use the aforementioned declares when I want to pixel zoom an image. And yes it sped it up ALOT

In the mean time I have added the declares to another project that uses a lot if if…then in the paint event.
Previously when scaling the window (with canvas) it was jerky to say the least on a Retina machine. With the declares the difference is HUGE, and I mean VERY HUGE.
And I do not see any quality lose (and my eyes are good ;-).

My experience: there are no drawbacks
Why not in the Xojo framework? I think Joe can enlighten this a bit. :wink:

For your discussion, here are the Apple Enumerations:

[quote]NSImageInterpolation
These interpolations are used by imageInterpolation and setImageInterpolation:.

enum {
NSImageInterpolationDefault = 0,
NSImageInterpolationNone = 1,
NSImageInterpolationLow = 2,
NSImageInterpolationMedium = 4,
NSImageInterpolationHigh = 3
};
typedef NSUInteger NSImageInterpolation;
Constants
NSImageInterpolationDefault
Use the context’s default interpolation.

Available in OS X v10.0 and later.

Declared in NSGraphicsContext.h.

NSImageInterpolationNone
No interpolation.

Available in OS X v10.0 and later.

Declared in NSGraphicsContext.h.

NSImageInterpolationLow
Fast, low-quality interpolation.

Available in OS X v10.0 and later.

Declared in NSGraphicsContext.h.

NSImageInterpolationMedium
Medium quality, slower than NSImageInterpolationLow.

Available in OS X v10.6 and later.

Declared in NSGraphicsContext.h.

NSImageInterpolationHigh
Highest quality, slower than NSImageInterpolationMedium.

Available in OS X v10.0 and later.

Declared in NSGraphicsContext.h.

[/quote]

We don’t change this setting on the context as there is probably a good reason for it being the default. I can’t say as I remember much more than that, but it’s possible that the system does different things when going to different output devices (screen, PDF, printer, etc).

It’s normally straightforward in Cocoa to change what you draw to suit where you are drawing it.

It is usually contained in the drawRect routine:

- (void)drawRect:(NSRect)rect
{

if ( [NSGraphicsContext currentContextDrawingToScreen] )
	{
	// draw to screen
	}
	else
	{
	// draw elsewhere
	}
	
}

I would say it depends on the content you are trying to scale. For some very small window icons I use on a iTunes-like mini window, lowering the interpolation has increased the quality – the icons are much crisper now. Which is not surprising when you consider what interpolating means to hard contrasts. For a portrait photo, this might be the wrong setting.

Wow, this is a great help, thanks Sam and Karen for bring it to my attention. I have an interface with a waveform image that needs constant resizing. This code has improved the responsiveness of my interface 10 fold. I see that the image is no longer smoothed (anti-aliased) as you zoom out, so I can see this wouldn’t help everyone, but for my purposes it’s perfect. Thank you!

This may not be applicable to your situation but if you study say iPhoto you will see that when it scrolls multiple images on the page it does it using a lower quality image. Only when the scrolling stops and the images are static does it then apply a high quality image.

I think it would be possible to implement a similar strategy within Xojo?

If you’re drawing icons, ideally you should have multiple representations, so that when drawn at a certain size (and DPI) they always look good.

However, for some things it’s unavoidable.

[quote=92631:@Terry Heaford]This may not be applicable to your situation but if you study say iPhoto you will see that when it scrolls multiple images on the page it does it using a lower quality image. Only when the scrolling stops and the images are static does it then apply a high quality image.

I think it would be possible to implement a similar strategy within Xojo?[/quote]
We’ve used similar techniques, especially during animation. Where we’d use a reduced size preview, often half the dimensions of the real preview and let the OS scale up. This does gain speed and we’ve never had any complaints about it.