Xojo 2016r1 xojo.graphics vs. NSGraphics for Retina

My app uses a mixture of xojo.graphics and nsGraphics methods to place pictures, drawings and formatted text on screen and in a printed document. Objects can be scaled, e.g. to fit within Print Preview windows and the like. I use both inside the same objects (e.g. canvas). Up until 2016r1 both coordinate systems used a common scaling factor which could be set using nsgraphics.ScaleCoordinates.

Because nsGraphics and xojo.graphics have different coordinate systems (the x axis is the same, but the y axis is inverted) I had to create some conversion methods, but both systems seemed to link to NSGraphics’ underlying scaling.

In 2016r1 Xojo seems to have separated the two scaling systems - and now seems to call its own graphics.scaleX and scaleY for the underlying scale - and so has messed up all my object positioning - particularly if you turn on Retina support in Xojo. I have tried setting scaleX and scaleY which works for non-retina but now if I move a window from a retina screen to a non-retina screen all the objects move around.

I have read the Xojo manual about Retina support several times but it doesn’t seem to address this issue. Does anyone have a good treatise about how to map the two coordinate systems, particularly when trying to support retina graphics and monitors.

Unable to test but Window and Canvas have the new event ScaleFactorChanged. That should fire when moved to the other monitor and you can update/switch your conversion methods.

Also, I’m not sure what your conversion method is doing, I use lots of CG declares and the first thing I do is call

Scale(1, -1) Translate(0, -Height)
then I can use the same Xojo coordinates for all my drawing.

Thanks Will.
After a fair bit of experimentation I’ve found out the following:

  1. The use of scale in graphics or nsgraphics should be mutually exclusive. i.e. only use the scaling factors in one, but not both environments as they seem to tangle each other up.
  2. There doesn’t seem to be a silver bullet conversion like you suggest, especially when using Retina mode. Setting either of the scalecoordinates to a negative number will flip the scale around, but also any text you place on it.
  3. I don’t seem to be able to get the translateCoordinates function to operate in any environment.
  4. It seems I have three choices:
    4.1 do scaling in graphics (using scaleX and scaleY) - you will need to flip the y axis and re-scale any text in nsgraphics
    4.2 do scaling in nsgraphics (using scalecoordinates) - now the y axis will need to be modified for both graphics and nsgraphics and any text in graphics will need to be re-scaled.
    4.3 do no scaling - still have to flip the y-axis for nsgraphics and re-scale text in both environments.

All of them require some complexity in translating x and y coordinate and sizes. For my purposes I need the ability to easily scale formatted text (i.e. rtf) so I have to do the scaling in nsGraphics and then manually adjust the positioning for the graphics environment.

Perhaps someone from Xojo might be able to comment incase there is a silver bullet somewhere.

May I ask why you are scaling a NSGrahicsContext?

I use NSGraphicsContext a lot without scaling and it always produces sharp results on Retina.

Flipping the co-ordinates should be done with math, the scale and translate will also flip pictures and text.

To apply a translate to a NSGraphicsContext, look at NSAffineTransform.

Hi Sam

I have a print preview window that includes a mixture of pictures, graphics, unformatted text and formatted text. The preview can be resized with all components resizing accordingly. Using NSGraphics was the only way I found of correctly scaling formatted (rtf) text within a canvas.

I’ve not looked at nsAffineTransform but will take a look.

Ah I see. Scaling Core Text is easiest when manipulating the context.

If it makes it any easier, you can get the CGContext from a NSGraphics Contaxt and draw/manipulate that. Personally I prefer using a CGContext as it feels more solid than using some of the NS Magic.

Are you using your own print preview or the OS print dialog with a preview specified?

Just for clarification, the two coordinate systems that were separated are measurements in regards to Picture.Width/Height (which are still measured in raw pixels) and Graphics.Width/Height (which are now measured in points). You should be able to get Graphics coordinates translated back to the underlying points by multiplying with the ScaleX and ScaleY properties.

It’s also worth noting that ScaleX and ScaleY are mutable, so you can modify them to change how things draw if necessary. Temporarily setting them to 1 before calling your NS declares and setting them back for your Xojo framework calls may give you what you’re looking for.

Thanks Greg for the clarity.