[Lazarus] Retina image lists on OS X

Zoë Peterson zoe at scootersoftware.com
Thu Oct 1 21:38:39 CEST 2015


The LCL-Carbon version of our application is retina enabled and looks 
fine except for one issue: TImageList.  On non-OS X platforms, 
Screen.PixelsPerInch is 100%/125%/150%/200% depending on the screen.  On 
OS X it always returns 72, the system APIs handle everything internally, 
and the lines/text are just smoother.  To draw the retina images you 
need to give it one twice as large and tell it to draw at the original 
100% size.

The problem with that is that TImageList's Width/Height properties are 
overloaded to mean both "the size of the bitmap" and "the size the image 
should be drawn at".  With the way scaling works on Windows (and 
presumably Linux), they're always the same, but on OS X they need to be 
different.

Nothing in TImageList is virtual, and the Width/Height access is used 
all over, so I can't work around the issue at a higher level. Using 
StretchDraw everywhere isn't sufficient, since things like TTreeView and 
toolbars adjust their sizes automatically. That leaves me with 3 
alternatives:

1) Use the existing Width/Height properties to mean "size of the 
bitmaps", and introduce new DisplayWidth/DisplayHeight ones that can 
customize the drawing.  Any code that looks at Width/Height for control 
positioning would need to use the new properties, and any that access 
the images would use the old ones.  The existing TImageList code would 
be mostly unchanged.

2) Use the existing Width/Height properties to mean "size of the drawn 
images" and introduce new BitmapWidth/Height ones that are the size of 
the bitmaps.  Internally TImageList would need to use the new properties 
almost entirely, as would any code that adds or removes images.

3) Somehow make OS X's scaling work the same as all of the other 
platforms and make Screen.PixelsPerInch adjust appropriately.

My feeling is that (3) is a bad idea since it would result in a mix of 
coordinate scaling depending on which window/display/API you're 
accessing.  I also don't know whether it's possible or what it would 
involve.  (1) and (2) seem like they're minor differences.  (2) seems 
more encapsulated, but also seems like it'll result in larger, more 
fragile patch.  (1) seems the cleanest conceptually, but also seems like 
it'll involve the most changes in third-party code.

Does anyone else have an opinion?  Is there an option I missed? If I did 
create a patch for (1) or (2) is it likely it would be merged? AFAIK the 
VCL doesn't have a distinction like this, but the default behavior would 
be to keep them in sync, so it would only matter for applications that 
took advantage of it.

-- 
Zoë Peterson
Scooter Software





More information about the Lazarus mailing list