OSX retina display - high resolution bitmaps

595 views
Skip to first unread message

Stefan Csomor

unread,
Jun 14, 2013, 11:42:54 AM6/14/13
to wx-...@googlegroups.com
Hi

I'm looking at best ways to implement support for retina 2 x resolution bitmaps. I'd like to make this as unobtrusive as possible. 

So one way would be adding a scale factor to bitmaps. There is a lot of code using wxBitmaps for about everything, I've looked eg at aui code, I could try to do some lazy instantiation of the bitmap internally, use 2x if it has been selected into a dc. But since wxBitmap offers access to its internals this is getting dangerous, as code expects GetHeight and RowBytes etc. to reflect on the real state. 

So there might have to be GetScaledHeight, GetScaledWidth and a CreateScaled calls, and a GetDisplayScale call or so on a dc ?

I'm thankful for your thoughts and opinions,

Best,

Stefan Csomor

Vadim Zeitlin

unread,
Jun 14, 2013, 3:11:33 PM6/14/13
to wx-...@googlegroups.com
On Fri, 14 Jun 2013 15:42:54 +0000 Stefan Csomor wrote:

SC> I'm looking at best ways to implement support for retina 2 x resolution
SC> bitmaps. I'd like to make this as unobtrusive as possible.

This would certainly be great. Unfortunately I don't know enough about
NSImage to understand what do we need to achieve this. According to my
(very limited) understanding, the HiDPI support in NSImage basically boils
down to

(a) Loading a file with "@2x" suffix appended to it if available.
(b) Changing the coordinate system so that the logical coordinates are
multiplied by 2.

Is this what you plan to do? And are the questions below (which I snipped
as I couldn't understand, let alone answer, them anyhow) about the factor
used for (2)?

Thanks for looking into this!
VZ

Stefan Csomor

unread,
Jun 14, 2013, 4:29:04 PM6/14/13
to wx-...@googlegroups.com
Hi

>This would certainly be great. Unfortunately I don't know enough about
>NSImage to understand what do we need to achieve this. According to my
>(very limited) understanding, the HiDPI support in NSImage basically boils
>down to
>
>(a) Loading a file with "@2x" suffix appended to it if available.
>(b) Changing the coordinate system so that the logical coordinates are
> multiplied by 2.
>
>Is this what you plan to do? And are the questions below (which I snipped
>as I couldn't understand, let alone answer, them anyhow) about the factor
>used for (2)?

no, that's the transparent support from NSImage, I'm aiming at something
different, and I haven't found a proper way to really make it
'transparent' to the developer, every attempt at doing so lead to problems
sooner or later in wx' own code already:

on retina displays the backing bitmap for a rect eg received for a paint
event is twice in both dimensions of the rect, so eg if you have to
repaint a 10x10 rect, the retina display has 20x20 pixels for this area.
So I thought about adding a GetScale to wxDC, which would return 2 for
such a display.

In code that now calls a wxBitmap::Create(10,10), which is then selected
into a wxMemoryDC, being painted on that way, resulting in a blurred
impression when blitted back (AUI and STC being the most promintent
casualties), we would change this code to
wxBitmap::CreateScaled(10,10,-1,dc->GetScale()) to really get a in-fact
20x20 pixel bitmap, so GetWidth() returns 20, GetScaledWidth() returns 10

Best,

Stefan

Vadim Zeitlin

unread,
Jun 14, 2013, 4:40:06 PM6/14/13
to wx-...@googlegroups.com
On Fri, 14 Jun 2013 20:29:04 +0000 Stefan Csomor wrote:

SC> on retina displays the backing bitmap for a rect eg received for a paint
SC> event is twice in both dimensions of the rect, so eg if you have to
SC> repaint a 10x10 rect, the retina display has 20x20 pixels for this area.
SC> So I thought about adding a GetScale to wxDC, which would return 2 for
SC> such a display.

Something is still not clear to me: suppose you have a window of the size
100 pixels (i.e. you created it with this size). What will be the size of
the update rectangle when fully repainting this window, 100 or 200?

Also, how does this work with text rendering, i.e. what is the value of
wxDC::GetTextExtent("W").x in HiDPI assuming it returns 10 in normal mode?


SC> In code that now calls a wxBitmap::Create(10,10), which is then selected
SC> into a wxMemoryDC, being painted on that way, resulting in a blurred
SC> impression when blitted back (AUI and STC being the most promintent
SC> casualties), we would change this code to
SC> wxBitmap::CreateScaled(10,10,-1,dc->GetScale()) to really get a in-fact
SC> 20x20 pixel bitmap, so GetWidth() returns 20, GetScaledWidth() returns 10

We still need to take the high(er) resolution bitmaps from somewhere
though. And we can't avoid having two versions of the bitmap because at
such small sizes you just can't rescale them automatically. And I don't see
how does this help with that...

Concerning the API itself, let me note that we already have wxBitmap()
ctor taking wxDC in wxMSW (but not wxGTK nor wxOSX AFAICS). So it could be
better to use wxDC scale behind the scenes instead of having to call
GetScaled() explicitly.

Regards,
VZ

Stefan Csomor

unread,
Jun 14, 2013, 4:56:45 PM6/14/13
to wx-...@googlegroups.com
Hi Vadim

>Something is still not clear to me: suppose you have a window of the size
>100 pixels (i.e. you created it with this size). What will be the size of
>the update rectangle when fully repainting this window, 100 or 200?

the window will be created with 100x100 points not pixels, so that it
looks the same on a retina and non-retina display, but on retina this
means 200x200 pixels, but this detail is not visible anywhere in the API
now

> Also, how does this work with text rendering, i.e. what is the value of
>wxDC::GetTextExtent("W").x in HiDPI assuming it returns 10 in normal mode?

does the same, paints 2x2 times as many pixels as on a non-retina display

>SC> In code that now calls a wxBitmap::Create(10,10), which is then
>selected
>SC> into a wxMemoryDC, being painted on that way, resulting in a blurred
>SC> impression when blitted back (AUI and STC being the most promintent
>SC> casualties), we would change this code to
>SC> wxBitmap::CreateScaled(10,10,-1,dc->GetScale()) to really get a
>in-fact
>SC> 20x20 pixel bitmap, so GetWidth() returns 20, GetScaledWidth()
>returns 10
>
> We still need to take the high(er) resolution bitmaps from somewhere
>though. And we can't avoid having two versions of the bitmap because at
>such small sizes you just can't rescale them automatically. And I don't
>see
>how does this help with that...

we get the scale factor from the dc, we have just one bitmap, internally
when used as a backing store I'm setting the scale factor on the
graphicscontext so that everything like text can continue do be rendered
as before with no changes necessary.

>Concerning the API itself, let me note that we already have wxBitmap()
>ctor taking wxDC in wxMSW (but not wxGTK nor wxOSX AFAICS). So it could be
>better to use wxDC scale behind the scenes instead of having to call
>GetScaled() explicitly.

if we just have a wxdc as param then this would be sufficient, but for
many of the uses cases we have now like in aui or stc, we just have width
and height, so we need a scale parameter, and since a lot of code is
accessing the real data of a bitmap, all existing API must reflect the
true pixel dimensions, but for drawing such a bitmap on a different dc
we'd need the scaled width and height.

Best Regards,

Stefan

Vadim Zeitlin

unread,
Jun 14, 2013, 9:58:51 PM6/14/13
to wx-...@googlegroups.com
On Fri, 14 Jun 2013 20:56:45 +0000 Stefan Csomor wrote:

SC> >Something is still not clear to me: suppose you have a window of the size
SC> >100 pixels (i.e. you created it with this size). What will be the size of
SC> >the update rectangle when fully repainting this window, 100 or 200?
SC>
SC> the window will be created with 100x100 points not pixels, so that it
SC> looks the same on a retina and non-retina display, but on retina this
SC> means 200x200 pixels, but this detail is not visible anywhere in the API
SC> now

Sorry for the continued questions but this is unfortunately still not
clear to me: if the distinction between points and pixels doesn't appear
anywhere in the API, why do we even speak about these "points" (I dislike
the word because of the confusion with 1/72th of an inch, which is clearly
a different "point")? AFAICS we should still continue to call them pixels
because we can't sub-address them, i.e. a window still must have an integer
size in these logical pixels and can't be e.g. 3 physical pixels wide.

Or am I misunderstanding something and do you plan to make this
logical/physical distinction appear anywhere in the API?


SC> > Also, how does this work with text rendering, i.e. what is the value of
SC> >wxDC::GetTextExtent("W").x in HiDPI assuming it returns 10 in normal mode?
SC>
SC> does the same, paints 2x2 times as many pixels as on a non-retina display

OK, I see, thanks.

SC> >SC> In code that now calls a wxBitmap::Create(10,10), which is then
SC> >selected
SC> >SC> into a wxMemoryDC, being painted on that way, resulting in a blurred
SC> >SC> impression when blitted back (AUI and STC being the most promintent
SC> >SC> casualties), we would change this code to
SC> >SC> wxBitmap::CreateScaled(10,10,-1,dc->GetScale()) to really get a
SC> >in-fact
SC> >SC> 20x20 pixel bitmap, so GetWidth() returns 20, GetScaledWidth()
SC> >returns 10
SC> >
SC> > We still need to take the high(er) resolution bitmaps from somewhere
SC> >though. And we can't avoid having two versions of the bitmap because at
SC> >such small sizes you just can't rescale them automatically. And I don't
SC> >see how does this help with that...
SC>
SC> we get the scale factor from the dc, we have just one bitmap, internally
SC> when used as a backing store I'm setting the scale factor on the
SC> graphicscontext so that everything like text can continue do be rendered
SC> as before with no changes necessary.

I think my confusion came from the fact that I was thinking about a
different problem: the one involving loading bitmaps from the disk files
(or resources). While you seem to be concerned only about the dynamically
generated bitmaps, i.e. those created programmatically. Is this right?

If so, could you please explain to me which problem exactly are we trying
to solve? Is it that when we draw the text to backing store bitmap and then
blit it on the screen we lose the precision? And, if this is so, is that
the only problem we have not counting the one with loading the external
resources of appropriate resolution?

SC> >Concerning the API itself, let me note that we already have wxBitmap()
SC> >ctor taking wxDC in wxMSW (but not wxGTK nor wxOSX AFAICS). So it could be
SC> >better to use wxDC scale behind the scenes instead of having to call
SC> >GetScaled() explicitly.
SC>
SC> if we just have a wxdc as param then this would be sufficient, but for
SC> many of the uses cases we have now like in aui or stc, we just have width
SC> and height, so we need a scale parameter

But where would the scale parameter come from? In your example in the
previous message it was returned from wxDC::GetScale() (which, BTW, would
be a pretty bad name because there are already plenty of scales in wxDC and
we really must choose some different word for this), i.e. you had to have a
wxDC to call it on anyhow.

SC> accessing the real data of a bitmap, all existing API must reflect the
SC> true pixel dimensions, but for drawing such a bitmap on a different dc
SC> we'd need the scaled width and height.

Sorry but I'm lost again... what are the "true pixel dimensions"? Logical
(10) or physical (20)?

Thanks again for bearing with my questions,
VZ

Stefan Csomor

unread,
Jun 14, 2013, 10:12:12 PM6/14/13
to wx-...@googlegroups.com
Hi Vadim

>Sorry for the continued questions but this is unfortunately still not
>clear to me: if the distinction between points and pixels doesn't appear
>anywhere in the API, why do we even speak about these "points" (I dislike
>the word because of the confusion with 1/72th of an inch, which is clearly
>a different "point")? AFAICS we should still continue to call them pixels
>because we can't sub-address them, i.e. a window still must have an
>integer
>size in these logical pixels and can't be e.g. 3 physical pixels wide.
>
> Or am I misunderstanding something and do you plan to make this
>logical/physical distinction appear anywhere in the API?

Apple names the property backingScaleFactor, it is a property of a screen,
of a window and of a device context, what they also have methods to convert

GContextConvertRectToDeviceSpace


>SC> we get the scale factor from the dc, we have just one bitmap,
>internally
>SC> when used as a backing store I'm setting the scale factor on the
>SC> graphicscontext so that everything like text can continue do be
>rendered
>SC> as before with no changes necessary.
>
> I think my confusion came from the fact that I was thinking about a
>different problem: the one involving loading bitmaps from the disk files
>(or resources). While you seem to be concerned only about the dynamically
>generated bitmaps, i.e. those created programmatically. Is this right?

yes, right now, yes, because we have current bug reports, the other
problem will have to be tackled but later

>If so, could you please explain to me which problem exactly are we trying
>to solve? Is it that when we draw the text to backing store bitmap and
>then
>blit it on the screen we lose the precision?

yes, that's the topic of AUI and STC - blurring

> And, if this is so, is that
>the only problem we have not counting the one with loading the external
>resources of appropriate resolution?

yes - apps get perceived as 'not supporting retina displays'

>SC> >Concerning the API itself, let me note that we already have
>wxBitmap()
>SC> >ctor taking wxDC in wxMSW (but not wxGTK nor wxOSX AFAICS). So it
>could be
>SC> >better to use wxDC scale behind the scenes instead of having to call
>SC> >GetScaled() explicitly.
>SC>
>SC> if we just have a wxdc as param then this would be sufficient, but for
>SC> many of the uses cases we have now like in aui or stc, we just have
>width
>SC> and height, so we need a scale parameter
>
> But where would the scale parameter come from? In your example in the
>previous message it was returned from wxDC::GetScale() (which, BTW, would
>be a pretty bad name because there are already plenty of scales in wxDC
>and
>we really must choose some different word for this), i.e. you had to have
>a
>wxDC to call it on anyhow.

so GetBackingScaleFactor as Apple themselves ?

>SC> accessing the real data of a bitmap, all existing API must reflect the
>SC> true pixel dimensions, but for drawing such a bitmap on a different dc
>SC> we'd need the scaled width and height.
>
> Sorry but I'm lost again... what are the "true pixel dimensions"? Logical
>(10) or physical (20)?

physical

>Thanks again for bearing with my questions,

thanks for helping me find a good solution,

Best,

Stefan

PS: in what time zone are you ;-) ?

Vadim Zeitlin

unread,
Jun 15, 2013, 8:56:43 AM6/15/13
to wx-...@googlegroups.com
On Sat, 15 Jun 2013 02:12:12 +0000 Stefan Csomor wrote:

SC> >If so, could you please explain to me which problem exactly are we trying
SC> >to solve? Is it that when we draw the text to backing store bitmap and
SC> >then blit it on the screen we lose the precision?
SC>
SC> yes, that's the topic of AUI and STC - blurring

OK, thanks for the confirmation and sorry again for misunderstanding you
initially.


[name of the function]
SC> so GetBackingScaleFactor as Apple themselves ?

I'd like something even more different. What about GetMagnificationFactor()?

BTW, Apple docs seem to say that this factor is guaranteed to be an
integer ("The fact that the backing scale factor is always a whole number
is another key feature of high resolution."), so this method should return
an integer and not a double as I initially thought. Unless we want to use
it under the other platforms too but I don't think Windows needs this and
I don't think GTK+ has any specific support for high DPI at all (does it?).


SC> >SC> accessing the real data of a bitmap, all existing API must reflect the
SC> >SC> true pixel dimensions, but for drawing such a bitmap on a different dc
SC> >SC> we'd need the scaled width and height.
SC> >
SC> > Sorry but I'm lost again... what are the "true pixel dimensions"? Logical
SC> >(10) or physical (20)?
SC>
SC> physical

After thinking about this for quite some time, I probably do agree that
physical pixel dimensions should be used in wxBitmap methods. But this is
clearly backwards incompatible (the existing code expects wxDC and wxBitmap
dimensions to be consistent) so we can't change this by default. So finally
I think I'm coming to your point of view -- if I understand it correctly
now -- and agree that we need some specific method for creating these
maybe-high-resolution bitmaps.

But I'd really like to see an example of some code that is affected by
blurring right now and how would it be changed to fix it. E.g. let's take
wxAuiTabContainer::Render() from src/aui/auibook.cpp which, I think, is an
example of this problem. AFAICS we need to change a few things in this
code:

1. wxMemoryDC ctor should take the original ("raw") DC it is associated
with to be able to use the same magnification factor as it. Luckily, we
already have wxMemoryDC(wxDC*) ctor, so we just need to use it here. And
implement this ctor correctly in src/osx/core/dcmemory.cpp, of course.

2. Next, the bitmap should be associated with the DC too. I still think
it'd be nice to reuse wxBitmap ctor taking wxDC because this will give
us more flexibility in the future (e.g., as a random example, we could
need the original DC to implement proper colour correction handling).
OTOH this is less explicit than using a more clear CreateScaled(). OT3H
CreateScaled() is somewhat misleading as it's not always going to be
scaled, it really just uses the same scale as wxDC does.

3. Here is where I'm still not sure... Does anything else need to be
changed? There are plenty of drawing calls done on this DC and they all
use logical pixel coordinates (of course), would any of them need to be
changed to use the device coordinates? DrawText() should clearly
continue to work (and produce crisp text) but what about DrawBitmap()
and Blit()? It seems like there should be physical pixel versions of
them, shouldn't there?


So for now I'm relatively sure that the current prologue of

wxMemoryDC dc;
dc.SetLayoutDirection(raw_dc->GetLayoutDirection());

wxBitmap bmp;
bmp.Create(m_rect.GetWidth(), m_rect.GetHeight());
dc.SelectObject(bmp);

needs to be replaced with

// Existing ctor which will be modified to call
// SetLayoutDirection() on all platforms and also do whatever is
// needed for high DPI support under OS X.
wxMemoryDC dc(raw_dc);
wxBitmap bmp(m_rect.GetSize(), dc); // new ctor
dc.SelectObject(bmp);


Or, actually, in my preferred style:

wxBitmap bmp(m_rect.GetSize(), *raw_dc);

// This ctor will need to be modified for OS X.
wxMemoryDC dc(bmp);

// SetLayoutDirection() call probably still needed?


But then I don't know what else needs to be changed and how. Could you
please show some examples of the changes that would be using the new API?

TIA,
VZ


SC> PS: in what time zone are you ;-) ?

My own personal one shifted by about 6 hours to whatever time zone I'm
currently in.

Stefan Csomor

unread,
Jun 15, 2013, 11:18:51 AM6/15/13
to wx-...@googlegroups.com
Hi

>I'd like something even more different. What about
>GetMagnificationFactor()?

I don't have any preferences, as long as not too much user code is using
it we can still change things if something better comes along ...

>
> BTW, Apple docs seem to say that this factor is guaranteed to be an
>integer ("The fact that the backing scale factor is always a whole number
>is another key feature of high resolution."), so this method should return
>an integer and not a double as I initially thought. Unless we want to use
>it under the other platforms too but I don't think Windows needs this and
>I don't think GTK+ has any specific support for high DPI at all (does
>it?).

it's an int, actually it used to be a float in earlier OSX versions - but
the hardware to use this never made it to the market - you were only able
to use this on simulated , but I guess in the end the decided it was too
much trouble - there still are no high-dpi iMacs or Mac Displays out, but
we cannot rule this out of course, now perhaps lets defer that decision
until we have all details carved out

btw you can simulate retina display:

http://stackoverflow.com/questions/12124576/how-to-simulate-a-retina-displa
y-hidpi-mode-in-mac-os-x-10-8-mountain-lion-on

>After thinking about this for quite some time, I probably do agree that
>physical pixel dimensions should be used in wxBitmap methods. But this is
>clearly backwards incompatible (the existing code expects wxDC and
>wxBitmap
>dimensions to be consistent) so we can't change this by default. So
>finally
>I think I'm coming to your point of view -- if I understand it correctly
>now -- and agree that we need some specific method for creating these
>maybe-high-resolution bitmaps.
>
> But I'd really like to see an example of some code that is affected by
>blurring right now and how would it be changed to fix it. E.g. let's take
>wxAuiTabContainer::Render() from src/aui/auibook.cpp which, I think, is an
>example of this problem. AFAICS we need to change a few things in this
>code:
>
>1. wxMemoryDC ctor should take the original ("raw") DC it is associated
> with to be able to use the same magnification factor as it. Luckily, we
> already have wxMemoryDC(wxDC*) ctor, so we just need to use it here.
>And
> implement this ctor correctly in src/osx/core/dcmemory.cpp, of course.

yes, that one needs to take over the scaling factor from the dc passed in

>
>2. Next, the bitmap should be associated with the DC too. I still think
> it'd be nice to reuse wxBitmap ctor taking wxDC because this will give
> us more flexibility in the future (e.g., as a random example, we could
> need the original DC to implement proper colour correction handling).

yes - while on a walk yesterday it occured to me that there was something
remotely similar with CreateCompatibleBitmap ;-)

> OTOH this is less explicit than using a more clear CreateScaled(). OT3H
> CreateScaled() is somewhat misleading as it's not always going to be
> scaled, it really just uses the same scale as wxDC does.

the bitmap itself would carry the scale in my API, I'll follow your API
suggestions and start implementing, to find out what might be missing

(..)

>But then I don't know what else needs to be changed and how. Could you
>please show some examples of the changes that would be using the new API?

I'm always testing against a modified stc sample which also features aui
tabs - so I have two systems hit by high-dpi under test

I'll be back ;-)

Thanks,

Stefan

Václav Slavík

unread,
Jun 15, 2013, 2:17:43 PM6/15/13
to wx-...@googlegroups.com

On 14 Jun 2013, at 22:29, Stefan Csomor <cso...@advancedconcepts.ch> wrote:
>> Is this what you plan to do? And are the questions below (which I snipped
>> as I couldn't understand, let alone answer, them anyhow) about the factor
>> used for (2)?
>
> no, that's the transparent support from NSImage, I'm aiming at something
> different

Isn't using NSImage for wxBitmap (or some other form of transparent support for 2x versions) a necessary step in any case? That alone would go a long way to making wx apps look better...

Vaclav

Stefan Csomor

unread,
Jun 15, 2013, 4:02:15 PM6/15/13
to wx-...@googlegroups.com
Hi
no, not necessarily, NSImage can be used for loading the best resources
for a certain resolution from the app's resources, so eg for artprovider
etc. or app specific resources. I'm using UIImage imageNamed: and NSImage
imageNamed: for these resources already in osx_cocoa and osx_iphone, so if
there are @2 images and we are running on a retina display these already
get used.

Best,

Stefan

Stefan Csomor

unread,
Jun 15, 2013, 11:53:39 PM6/15/13
to wx-...@googlegroups.com
Hi

right now I have done the following

- internally a dc now has a LogicalScale of 2 in case of a retina display

I've then modified the wxAuiTabContainer::Render a little bit and this now
gives me crisp tabs

// create off-screen bitmap
double sx, sy;
raw_dc->GetLogicalScale(&sx, &sy);
bmp.Create(m_rect.GetWidth()*sx, m_rect.GetHeight()*sy);
dc.SelectObject(bmp);
dc.SetLogicalScale(sx, sy);

so the question now is which of this should we automate / wrap into API
without running into problems:


MemoryDC
--------

>1. wxMemoryDC ctor should take the original ("raw") DC it is associated
> with to be able to use the same magnification factor as it. Luckily, we
> already have wxMemoryDC(wxDC*) ctor, so we just need to use it here.
>And
> implement this ctor correctly in src/osx/core/dcmemory.cpp, of course.

calling this with the rawdc could copy logical scale,

double sx, sy;
raw_dc->GetLogicalScale(&sx, &sy);
dc.SetLogicalScale(sx, sy);

could this be introducing problems,? as right now, there is no such
behaviour, should we make it explicit by adding a CopyLogicalScale(wxDC dc)




Bitmap
------

> 2. Next, the bitmap should be associated with the DC too. I still think
> it'd be nice to reuse wxBitmap ctor taking wxDC because this will give
> us more flexibility in the future (e.g., as a random example, we could
> need the original DC to implement proper colour correction handling).
> OTOH this is less explicit than using a more clear CreateScaled(). OT3H
> CreateScaled() is somewhat misleading as it's not always going to be
> scaled, it really just uses the same scale as wxDC does.


wxBitmap(width,height,dc) didn't exist before, so there's no OSX code
using it, this could be interpreted as above

double sx, sy;
raw_dc->GetLogicalScale(&sx, &sy);
bmp.Create(m_rect.GetWidth()*sx, m_rect.GetHeight()*sy);

but that's not what it does under msw - width and height are always in
pixels, I don't think this is wise, so I still would prefer an explicit
CreateScaled, we wouldn't need an explicit scale factor (but we might need
such a thing later in order to have multiple scale factors for our
resource-bitmaps) we can deduce it from the dc:


bmp.CreateScaled(logwidth,logheight,dc) which would translate logical into
device units and then call Create(devwidth,devheight,dc) interally, we can
have this implemented on all platforms

>3. Here is where I'm still not sure... Does anything else need to be
> changed? There are plenty of drawing calls done on this DC and they all
> use logical pixel coordinates (of course), would any of them need to be
> changed to use the device coordinates? DrawText() should clearly
> continue to work (and produce crisp text) but what about DrawBitmap()
> and Blit()? It seems like there should be physical pixel versions of
> them, shouldn't there?

all methods should continue to use logical coordinates in the publicly
visible API so that nothing changes in existing code,

Blits take a source dc so that is fine, as eg in our example above the
memdc has a 'higher resolution backing store' so the blit at the end of
the Render method 'just works'

I still think that wxBitmap would benefit from keeping the information
about the scale, when created from the above CreateScaled, it might keep
the LogicalScale information and then we could use LogicalWidth/Height (or
ScaledWidth/Height) when having to DrawBitmap. This LogicalFactor should
be definable explicitly in a CreateScaled call, because of the following
problem:

We need high-res resources/artwork in order for things to look pretty, but
we don't need everything as well in low-res, if the bitmap itself knows
that its 2x, on an ordinary display this just would get scaled down.

if the bitmap knows about its logical scale, then your memdc from bitmap
would work as well

>Bitmap bmp;
>bmp.CreateScaled(m_rect.GetSize(), *raw_dc);
>
>wxMemoryDC dc(bmp);

I guess also a SelectBitmap would then read the Logical Scale and adapt
itself then my question of whether the wxMemory from raw_dc constructor
would copy the logical scale would be irrelevant, it wouldn't have to do
so, as it can read it from the bitmap Š

Thanks,

Stefan

Stefan Csomor

unread,
Jun 16, 2013, 1:39:48 AM6/16/13
to wx-...@googlegroups.com
Hi

as on the dc the GetLogicalScale(x,y) is reflecting on the scale, would

double GetLogicalScale() on a window be a more consistent name than
GetMagnificationFactor()?

and yes, I'd like to keep it a double (was we don't need a different val
for x than for y we can make it the return value), the OSX internal API is
also using doubles, and using doubles we are prepared for what the future
brings ..

Thanks,

Stefan

Vadim Zeitlin

unread,
Jun 16, 2013, 7:14:32 AM6/16/13
to wx-...@googlegroups.com
On Sun, 16 Jun 2013 03:53:39 +0000 Stefan Csomor wrote:

SC> - internally a dc now has a LogicalScale of 2 in case of a retina display

I'm afraid that reusing the existing logical scale is not ideal. I'd
expect any code already using it for its own purposes to break. This is why
I thought we needed a separate "magnification factor" in the first place.
For me this is by far the most serious problem with your current approach,
so I'd like to understand why did you decide to do it like this finally?
Was it just too complicated to add multiplications/divisions by the
magnification factor everywhere it's needed or is there something else? If
so, it seems to me that you could easily use logical scale internally as
you do now but divide it by (separately stored) magnification factor in
the public GetLogicalScale(). Or am I missing some deeper problem here?


SC> I've then modified the wxAuiTabContainer::Render a little bit and this now
SC> gives me crisp tabs
SC>
SC> // create off-screen bitmap
SC> double sx, sy;
SC> raw_dc->GetLogicalScale(&sx, &sy);
SC> bmp.Create(m_rect.GetWidth()*sx, m_rect.GetHeight()*sy);
SC> dc.SelectObject(bmp);
SC> dc.SetLogicalScale(sx, sy);
SC>
SC> so the question now is which of this should we automate / wrap into API
SC> without running into problems:

I'd definitely like to improve on the above...


SC> MemoryDC
SC> --------
SC>
SC> >1. wxMemoryDC ctor should take the original ("raw") DC it is associated
SC> > with to be able to use the same magnification factor as it. Luckily, we
SC> > already have wxMemoryDC(wxDC*) ctor, so we just need to use it here.
SC> > And implement this ctor correctly in src/osx/core/dcmemory.cpp, of
SC> > course.
SC>
SC> calling this with the rawdc could copy logical scale,
SC>
SC> double sx, sy;
SC> raw_dc->GetLogicalScale(&sx, &sy);
SC> dc.SetLogicalScale(sx, sy);

Yes, I think this ctor should do this.

SC> could this be introducing problems,? as right now, there is no such
SC> behaviour, should we make it explicit by adding a CopyLogicalScale(wxDC dc)

I don't think it's going to introduce problems because the code would
still need to be modified to pass the extra "original DC" parameter to
wxMemoryDC ctor. But, to repeat, it's the reuse of the logical scale
internally, instead of using a separate variable, that could definitely
introduce problems.


SC> Bitmap
SC> ------
SC>
SC> > 2. Next, the bitmap should be associated with the DC too. I still think
SC> > it'd be nice to reuse wxBitmap ctor taking wxDC because this will give
SC> > us more flexibility in the future (e.g., as a random example, we could
SC> > need the original DC to implement proper colour correction handling).
SC> > OTOH this is less explicit than using a more clear CreateScaled(). OT3H
SC> > CreateScaled() is somewhat misleading as it's not always going to be
SC> > scaled, it really just uses the same scale as wxDC does.
SC>
SC>
SC> wxBitmap(width,height,dc) didn't exist before, so there's no OSX code
SC> using it, this could be interpreted as above
SC>
SC> double sx, sy;
SC> raw_dc->GetLogicalScale(&sx, &sy);
SC> bmp.Create(m_rect.GetWidth()*sx, m_rect.GetHeight()*sy);
SC>
SC> but that's not what it does under msw - width and height are always in
SC> pixels,

Well, yes, but again, if we used a separate magnification factor, which
would be, at least for now, always 1 under MSW, this wouldn't be a problem,
they'd still remain in pixels.

SC> I don't think this is wise, so I still would prefer an explicit
SC> CreateScaled, we wouldn't need an explicit scale factor (but we might need
SC> such a thing later in order to have multiple scale factors for our
SC> resource-bitmaps) we can deduce it from the dc:
SC>
SC> bmp.CreateScaled(logwidth,logheight,dc) which would translate logical into
SC> device units and then call Create(devwidth,devheight,dc) interally, we can
SC> have this implemented on all platforms

Sorry, I don't see the advantage of calling it CreateScaled() compared to
just Create(). If we don't even pass a scale to it, this method might be
doing something else/more than just scaling in the future and its name
would become misleading. If we really need a different name for this
method, let's call it CreateCompatible(), using the classic MSW term, or
CreateFor(dc) to avoid being too MSW-specific.

Of course, CreateScaled() is not a catastrophe neither, but personally I
think Create() is more uniform and generally nicer.


SC> >3. Here is where I'm still not sure... Does anything else need to be
SC> > changed? There are plenty of drawing calls done on this DC and they all
SC> > use logical pixel coordinates (of course), would any of them need to be
SC> > changed to use the device coordinates? DrawText() should clearly
SC> > continue to work (and produce crisp text) but what about DrawBitmap()
SC> > and Blit()? It seems like there should be physical pixel versions of
SC> > them, shouldn't there?
SC>
SC> all methods should continue to use logical coordinates in the publicly
SC> visible API so that nothing changes in existing code,
SC>
SC> Blits take a source dc so that is fine, as eg in our example above the
SC> memdc has a 'higher resolution backing store' so the blit at the end of
SC> the Render method 'just works'
SC>
SC> I still think that wxBitmap would benefit from keeping the information
SC> about the scale,

FWIW I do agree with this.

SC> We need high-res resources/artwork in order for things to look pretty, but
SC> we don't need everything as well in low-res, if the bitmap itself knows
SC> that its 2x, on an ordinary display this just would get scaled down.

I don't think it's the best approach. Scaling small bitmaps automatically
makes them look pretty bad and I expect people serious about their
applications appearances to have two manually created copies of the bitmaps
for each resolution.

OTOH I have no idea how are we going to handle having maybe one and maybe
two bitmap representations of the same bitmap at the API level. We already
have wxIconBundle which could do this, but it's not really a drop in
replacement for wxBitmap :-(


SC> if the bitmap knows about its logical scale, then your memdc from bitmap
SC> would work as well
SC>
SC> >Bitmap bmp;
SC> >bmp.CreateScaled(m_rect.GetSize(), *raw_dc);
SC> >
SC> >wxMemoryDC dc(bmp);
SC>
SC> I guess also a SelectBitmap would then read the Logical Scale and adapt
SC> itself then my question of whether the wxMemory from raw_dc constructor
SC> would copy the logical scale would be irrelevant, it wouldn't have to do
SC> so, as it can read it from the bitmap Š

I actually still think we should do both. Why not?

Regards,
VZ

Vadim Zeitlin

unread,
Jun 16, 2013, 7:17:42 AM6/16/13
to wx-...@googlegroups.com
On Sun, 16 Jun 2013 05:39:48 +0000 Stefan Csomor wrote:

SC> as on the dc the GetLogicalScale(x,y) is reflecting on the scale, would
SC> double GetLogicalScale() on a window be a more consistent name than
SC> GetMagnificationFactor()?

As you've probably noticed from my reply to your previous message, I'd
strongly prefer to add GetMagnificationFactor() to wxDC instead. If we
don't/can't do this, then I agree that having GetLogicalScale() in wxWindow
would be logical, it would be consistent with other methods such as
GetTextExtent() that already exist in both classes.

SC> and yes, I'd like to keep it a double (was we don't need a different val
SC> for x than for y we can make it the return value), the OSX internal API is
SC> also using doubles, and using doubles we are prepared for what the future
SC> brings ..

Well, from the point of view of compatibility double does look safer. But
it also forces you to think about rounding when creating bitmaps and such
that I'd rather avoid. But I'm generally floating-point-phobic and always
expect to run into problems when using them. Perhaps in this particular
case my fears are misplaced.

Regards,
VZ

Stefan Csomor

unread,
Jun 16, 2013, 9:42:28 AM6/16/13
to wx-...@googlegroups.com
Hi

>SC> - internally a dc now has a LogicalScale of 2 in case of a retina
>display
>
> I'm afraid that reusing the existing logical scale is not ideal. I'd
>expect any code already using it for its own purposes to break. This is
>why
>I thought we needed a separate "magnification factor" in the first place.
>For me this is by far the most serious problem with your current approach,
>so I'd like to understand why did you decide to do it like this finally?
>Was it just too complicated to add multiplications/divisions by the
>magnification factor everywhere it's needed or is there something else? If
>so, it seems to me that you could easily use logical scale internally as
>you do now but divide it by (separately stored) magnification factor in
>the public GetLogicalScale(). Or am I missing some deeper problem here?

I'm still having a m_magnificationFactor internally, I wrapped it into
logicalScale because actually that's was it is (and the way how I'm
recognizing it on a CGGraphicsContext is via doing a logical -> device
coord conversions, so it's built into the OS. But I can avoid that, I'm
not using native RectToDevice conversions anywhere else in my code. I'll
rewire this and see whether this gets me into problems

>SC> calling this with the rawdc could copy logical scale,
>SC>
>SC> double sx, sy;
>SC> raw_dc->GetLogicalScale(&sx, &sy);
>SC> dc.SetLogicalScale(sx, sy);
>
> Yes, I think this ctor should do this.

with the later changes of creating the bitmap from the dc - it's at the
SelectBitmap moment that MagnificationFactor would be copied back
but we agree that the 'real' pixels of a

wxBitmap::Create(width,height,dc)

would be width*dc.GetMagnification() factor, and that I don't have to do
that multiplication as a wxBitmap user

>
>SC> I don't think this is wise, so I still would prefer an explicit
>SC> CreateScaled, we wouldn't need an explicit scale factor (but we might
>need
>SC> such a thing later in order to have multiple scale factors for our
>SC> resource-bitmaps) we can deduce it from the dc:
>SC>
>SC> bmp.CreateScaled(logwidth,logheight,dc) which would translate logical
>into
>SC> device units and then call Create(devwidth,devheight,dc) interally,
>we can
>SC> have this implemented on all platforms
>
> Sorry, I don't see the advantage of calling it CreateScaled() compared to
>just Create(). If we don't even pass a scale to it, this method might be
>doing something else/more than just scaling in the future and its name
>would become misleading. If we really need a different name for this
>method, let's call it CreateCompatible(), using the classic MSW term, or
>CreateFor(dc) to avoid being too MSW-specific.
>
> Of course, CreateScaled() is not a catastrophe neither, but personally I
>think Create() is more uniform and generally nicer.

I still have to solve the use case of explicitly having to create such a
bitmap, see farther down

>SC> We need high-res resources/artwork in order for things to look
>pretty, but
>SC> we don't need everything as well in low-res, if the bitmap itself
>knows
>SC> that its 2x, on an ordinary display this just would get scaled down.
>
> I don't think it's the best approach. Scaling small bitmaps automatically
>makes them look pretty bad and I expect people serious about their
>applications appearances to have two manually created copies of the
>bitmaps
>for each resolution.
>
> OTOH I have no idea how are we going to handle having maybe one and maybe
>two bitmap representations of the same bitmap at the API level. We already
>have wxIconBundle which could do this, but it's not really a drop in
>replacement for wxBitmap :-(

right now bitmaps are drawing via taking their pixel width as logical
width, which on high dpi displays results in blurred bitmaps, so we cannot
change the interpretation there, but I need a way to construct a bitmap
that will be drawn 'pixel by pixel' on such a device. Also eg in stc at
the moment the backing bitmap is created, there is no dc around yet, so
right now I did a
wxBitmap::CreateScaled(width,height,winid->GetMagnificationFactor())

So the Create call that takes the dc is ok, if we keep the magnification
factor separate, but I need a name for creating a high-dpi bitmap
explicitly, and for retrieving the 'scaled' ie logical width for such a
bitmap, so right now this would be

CreateScaled
GetScaledWidth
GetScaledHeight
GetMagnificationFactor

we need quartett of names, so it could well be

CreateMagnified
GetScaledWidth
GetScaledHeight
GetMagnificationFactor

?


>I actually still think we should do both. Why not?

because it's not needed, and there will be situations where things might
collide - if we declare that the bitmap has to be created 'compatible' via
using the correct constructor/create calls. Then I cannot keep the
'former' magnification factor taken from copying from the rawdc. I've
tried several versions, and keeping it in the bitmap, setting in the
'SelectBitmap' is the most consistent and easy to understand version.

Thanks,

Stefan

Stefan Csomor

unread,
Jun 16, 2013, 10:13:59 AM6/16/13
to wx-...@googlegroups.com
Hi

>As you've probably noticed from my reply to your previous message, I'd
>strongly prefer to add GetMagnificationFactor() to wxDC instead. If we
>don't/can't do this, then I agree that having GetLogicalScale() in
>wxWindow
>would be logical, it would be consistent with other methods such as
>GetTextExtent() that already exist in both classes.

I'll add a GetMagnificationFactor to wxDC

>SC> and yes, I'd like to keep it a double (was we don't need a different
>val
>SC> for x than for y we can make it the return value), the OSX internal
>API is
>SC> also using doubles, and using doubles we are prepared for what the
>future
>SC> brings ..
>
> Well, from the point of view of compatibility double does look safer. But
>it also forces you to think about rounding when creating bitmaps and such
>that I'd rather avoid. But I'm generally floating-point-phobic and always
>expect to run into problems when using them. Perhaps in this particular
>case my fears are misplaced.

yes, I have the same apprehensions against floats, they're never my first
choice ;-) but I didn't want to limit the API from the start, and I think
since we will use this in multiplications and divisions which quickly will
be rounded - I don't think rounding errors will propagate.

Thanks,

STefan

Vadim Zeitlin

unread,
Jun 16, 2013, 11:11:26 AM6/16/13
to wx-...@googlegroups.com
On Sun, 16 Jun 2013 13:42:28 +0000 Stefan Csomor wrote:

SC> I'm still having a m_magnificationFactor internally, I wrapped it into
SC> logicalScale because actually that's was it is

Yes, I understand this, but I think the existing code using logical scale
could easily be broken by the scale being already set on the DCs it
operates on by wxWidgets, where it was always supposed to be governed
exclusively by the user code before. It could be useful to try the drawing
sample with your current changes, I'm almost certain that something in it
must be broken by them.


SC> >SC> calling this with the rawdc could copy logical scale,
SC> >SC>
SC> >SC> double sx, sy;
SC> >SC> raw_dc->GetLogicalScale(&sx, &sy);
SC> >SC> dc.SetLogicalScale(sx, sy);
SC> >
SC> > Yes, I think this ctor should do this.
SC>
SC> with the later changes of creating the bitmap from the dc - it's at the
SC> SelectBitmap moment that MagnificationFactor would be copied back

OK, thinking more about this, I agree with you that we should take the
magnification factor only from the bitmap, not from the source DC. Although
normally they should be the same, shouldn't they?


SC> >SC> wxBitmap(width,height,dc) didn't exist before, so there's no OSX code
SC> >SC> using it, this could be interpreted as above
SC> >SC>
SC> >SC> double sx, sy;
SC> >SC> raw_dc->GetLogicalScale(&sx, &sy);
SC> >SC> bmp.Create(m_rect.GetWidth()*sx, m_rect.GetHeight()*sy);
SC> >SC>
SC> >SC> but that's not what it does under msw - width and height are always in
SC> >SC> pixels,
SC> >
SC> > Well, yes, but again, if we used a separate magnification factor, which
SC> >would be, at least for now, always 1 under MSW, this wouldn't be a
SC> >problem, they'd still remain in pixels.
SC>
SC> but we agree that the 'real' pixels of a
SC>
SC> wxBitmap::Create(width,height,dc)
SC>
SC> would be width*dc.GetMagnification() factor, and that I don't have to do
SC> that multiplication as a wxBitmap user

Just to be sure we're speaking about the same thing: you don't have to do
it in the ctor/Create(). But you'd still have to deal with it if you want
to operate on wxBitmap pixels, right? E.g. you'd have 2*width pixels per
line when using raw bitmap iterators; converting this bitmap to wxImage
would give you a wxImage of size (2*width, 2*height) and so on.


SC> > OTOH I have no idea how are we going to handle having maybe one and maybe
SC> >two bitmap representations of the same bitmap at the API level. We already
SC> >have wxIconBundle which could do this, but it's not really a drop in
SC> >replacement for wxBitmap :-(

I'll continue the discussion below but I don't think you're taking into
account this problem at all, do you? Maybe you think that wxBitmap is never
going to use 2 representations at once because it's always going to be
loaded from either a standard image or a "@2x" one? I'm not sure if this is
true however, as there could be some weird cases like starting a program on
a low DPI external display and then moving its window to the built-in high
DPI display of the notebook. Granted, this is slightly less urgent...


SC> right now bitmaps are drawing via taking their pixel width as logical
SC> width, which on high dpi displays results in blurred bitmaps, so we cannot
SC> change the interpretation there, but I need a way to construct a bitmap
SC> that will be drawn 'pixel by pixel' on such a device.

Wait, I'm starting to be lost again. For me the "logical size" is the size
specified in the ctor. If you also pass wxBitmap ctor a wxDC which has a
magnification factor of 2, the "physical size" of the bitmap will be twice
as big as its logical size. And then if you draw such a bitmap using its
logical size, it will be already drawn "pixel by pixel", i.e. without any
scaling. Am I wrong somewhere here?

SC> Also eg in stc at the moment the backing bitmap is created, there is no
SC> dc around yet, so right now I did a
SC> wxBitmap::CreateScaled(width,height,winid->GetMagnificationFactor())

Good point... So we can't just have a Create(size, dc) after all. Oh well.

SC> So the Create call that takes the dc is ok, if we keep the magnification
SC> factor separate, but I need a name for creating a high-dpi bitmap
SC> explicitly, and for retrieving the 'scaled' ie logical width for such a
SC> bitmap, so right now this would be
SC>
SC> CreateScaled
SC> GetScaledWidth
SC> GetScaledHeight
SC> GetMagnificationFactor
SC>
SC> we need quartett of names, so it could well be
SC>
SC> CreateMagnified
SC> GetScaledWidth
SC> GetScaledHeight
SC> GetMagnificationFactor
SC>
SC> ?

This does seem rather inconsistent :-( So we're back to CreateScaled() and
GetScaleFactor(), I guess.

Regards,
VZ

Stefan Csomor

unread,
Jun 16, 2013, 11:39:30 AM6/16/13
to wx-...@googlegroups.com
Hi

>SC> I'm still having a m_magnificationFactor internally, I wrapped it into
>SC> logicalScale because actually that's was it is
>
> Yes, I understand this, but I think the existing code using logical scale
>could easily be broken by the scale being already set on the DCs it
>operates on by wxWidgets, where it was always supposed to be governed
>exclusively by the user code before. It could be useful to try the drawing
>sample with your current changes, I'm almost certain that something in it
>must be broken by them.

yes, I'm fine with that reasoning, that's why I said I'm rewiring things
now to leave LogicalScale out of the game and use MagnificationFactor
throughout

>SC> >SC> calling this with the rawdc could copy logical scale,
>SC> >SC>
>SC> >SC> double sx, sy;
>SC> >SC> raw_dc->GetLogicalScale(&sx, &sy);
>SC> >SC> dc.SetLogicalScale(sx, sy);
>SC> >
>SC> > Yes, I think this ctor should do this.
>SC>
>SC> with the later changes of creating the bitmap from the dc - it's at
>the
>SC> SelectBitmap moment that MagnificationFactor would be copied back
>
> OK, thinking more about this, I agree with you that we should take the
>magnification factor only from the bitmap, not from the source DC.
>Although
>normally they should be the same, shouldn't they?

yes, but that we all the code that does not construct the memdc from the
dc at all, like in aui does not have it set at all before its SelectBitmap
is called, so that's why I'll only set it then
wxBitmap::wxBitmap(width,height,dc) and wxBitmap::Create(width,height,dc)
would both take the magnification factor from the dc (interpret width and
height more as 'logical' dimensions) and then call
Create(width*factor,height*factor) internally, so that all code iterating
over the raw data will never have to be changed, and yes a wxImage would
have a size of factor*width,factor*height (we might put something into a
Resolution option)

>
>SC> > OTOH I have no idea how are we going to handle having maybe one and
>maybe
>SC> >two bitmap representations of the same bitmap at the API level. We
>already
>SC> >have wxIconBundle which could do this, but it's not really a drop in
>SC> >replacement for wxBitmap :-(
>
> I'll continue the discussion below but I don't think you're taking into
>account this problem at all, do you? Maybe you think that wxBitmap is
>never
>going to use 2 representations at once because it's always going to be
>loaded from either a standard image or a "@2x" one? I'm not sure if this
>is
>true however, as there could be some weird cases like starting a program
>on
>a low DPI external display and then moving its window to the built-in high
>DPI display of the notebook. Granted, this is slightly less urgent...

I'm aware of the need for a bitmap-bundle, I thought about this as a
bundle of bitmaps from which the code would select the one best matching
its magnification factor, but wanted to defer that for the momen

>SC> right now bitmaps are drawing via taking their pixel width as logical
>SC> width, which on high dpi displays results in blurred bitmaps, so we
>cannot
>SC> change the interpretation there, but I need a way to construct a
>bitmap
>SC> that will be drawn 'pixel by pixel' on such a device.
>
> Wait, I'm starting to be lost again. For me the "logical size" is the
>size
>specified in the ctor. If you also pass wxBitmap ctor a wxDC which has a
>magnification factor of 2, the "physical size" of the bitmap will be twice
>as big as its logical size. And then if you draw such a bitmap using its
>logical size, it will be already drawn "pixel by pixel", i.e. without any
>scaling. Am I wrong somewhere here?

but in order to do that, I need GetScaledWidth and GetScaledHeight - since
all our drawing code is using logical coordinates

so

void wxGCDCImpl::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y,
bool useMask )
{
wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid DC") );
wxCHECK_RET( bmp.IsOk(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid
bitmap") );

int w = bmp.GetWidth();
int h = bmp.GetHeight();
(..)
m_graphicContext->DrawBitmap( bmp, x, y, w, h );
}


will have to be changed to

int w = bmp.GetScaledWidth() ...

>
>SC> Also eg in stc at the moment the backing bitmap is created, there is
>no
>SC> dc around yet, so right now I did a
>SC> wxBitmap::CreateScaled(width,height,winid->GetMagnificationFactor())
>
> Good point... So we can't just have a Create(size, dc) after all. Oh
>well.

but yes, we can, because the dc is having its Magnification Factor exposed

wxDC::Create(size,dc)
{
CreateScaled(size,dc.GetMagnificationFactor()
}

>SC> So the Create call that takes the dc is ok, if we keep the
>magnification
>SC> factor separate, but I need a name for creating a high-dpi bitmap
>SC> explicitly, and for retrieving the 'scaled' ie logical width for such
>a
>SC> bitmap, so right now this would be
>SC>
>SC> CreateScaled
>SC> GetScaledWidth
>SC> GetScaledHeight
>SC> GetMagnificationFactor
>SC>
>SC> we need quartett of names, so it could well be
>SC>
>SC> CreateMagnified
>SC> GetScaledWidth
>SC> GetScaledHeight
>SC> GetMagnificationFactor
>SC>
>SC> ?
>
> This does seem rather inconsistent :-( So we're back to CreateScaled()
>and
>GetScaleFactor(), I guess.

I'm not sure, if we have MagnificationFactor we might also have a
GetScaled .. it doesn't really bite that badly IMHO

Thanks,

Stefan

Paul K

unread,
Jun 17, 2013, 12:18:17 PM6/17/13
to wx-...@googlegroups.com
Stefan:
 
>>If so, could you please explain to me which problem exactly are we trying
>>to solve? Is it that when we draw the text to backing store bitmap and
>>then blit it on the screen we lose the precision?

> yes, that's the topic of AUI and STC - blurring
 
Thank you for looking into this; I was just discussing this with Vadim in wx-users few days ago. STC blur should be easy to solve: just call editor:SetBufferedDraw(false). Unfortunately, it's causing an issue with indicators that have alpha property set as I described here: https://groups.google.com/d/msg/wx-users/mJqkdReO_-M/-oGvj8ft_V4J
 
AUI blur does indeed need to be fixed and it shows up in AUI bitmaps and in fonts used in some places (like AuiNotebook tabs): https://groups.google.com/d/msg/wx-users/mJqkdReO_-M/Sw21mvdPE3IJ
 
Paul.

Message has been deleted

Stefan Csomor

unread,
Jun 17, 2013, 1:04:00 PM6/17/13
to wx-...@googlegroups.com
Hi
> yes, that's the topic of AUI and STC - blurring
 
Thank you for looking into this; I was just discussing this with Vadim in wx-users few days ago. STC blur should be easy to solve: just call editor:SetBufferedDraw(false). Unfortunately, it's causing an issue with indicators that have alpha property set as I described here: https://groups.google.com/d/msg/wx-users/mJqkdReO_-M/-oGvj8ft_V4J
 

you are welcome, that's why the best attempt is to have the buffer being high-dpi and not having to avoid double buffering, I have everything working right now in my sandbox, 

AUI blur does indeed need to be fixed and it shows up in AUI bitmaps and in fonts used in some places (like AuiNotebook tabs): https://groups.google.com/d/msg/wx-users/mJqkdReO_-M/Sw21mvdPE3IJ

yes, the only place where some love is needed right now, to have those graphics at 2x resolution as well.

I'll land the commits in the next few days

Best,

Stefan

Stefan Csomor

unread,
Jun 17, 2013, 1:52:02 PM6/17/13
to wx-...@googlegroups.com
Hi Vadim

I've committed the GetMagnificationSupport support for wxWindow, next
would be wxBitmap, I have some questions for this:
- what method names should I take ?

- should I provide a

common impl boilerplate code in wxBitmapBase like

virtual bool CreateScaled - which would ignore the scale factor - should I
assert on a diff from 1.0 ? , as it needs platform support

virtual bool Create( .. wxDC ) which would ignore the dc

so that I don't have to invade the platform implementations

Thanks,

Stefan

Paul K

unread,
Jun 17, 2013, 2:19:02 PM6/17/13
to wx-...@googlegroups.com
Stefan:
 
> you are welcome, that's why the best attempt is to have the buffer being high-dpi and not having to avoid double buffering, I have everything working right now in my sandbox,
 
Sounds great; do you expect this to work "out of the box" or would there be any API call to turn Retina support on?
 
> yes, the only place where some love is needed right now, to have those graphics at 2x resolution as well.
> I'll land the commits in the next few days
 
I use my own ArtProvider that loads toolbar bitmaps directly using wxBitmap. Does this mean that I only need to provide @2 resolution files and any "wx.wxBitmap(file)" call will pick those for Retina displays?
 
Paul.
 

Robin Dunn

unread,
Jun 17, 2013, 3:04:55 PM6/17/13
to wx-...@googlegroups.com
Stefan Csomor wrote:
> Hi Vadim
>
> I've committed the GetMagnificationSupport support for wxWindow, next
> would be wxBitmap,

Hi Stefan,

Looks like there is a compilation issue with your last commit:

http://buildbot.wxpython.org:8010/builders/build-osx-py27-2/builds/895/steps/shell/logs/stdio

/Users/robind/projects/buildbots/osx-10.7-vm-py2.7/build-osx-py27-2/wxWidgets/src/osx/cocoa/nonownedwnd.mm:
In member function �virtual double
wxNonOwnedWindowCocoaImpl::GetMagnificationFactor() const�:
/Users/robind/projects/buildbots/osx-10.7-vm-py2.7/build-osx-py27-2/wxWidgets/src/osx/cocoa/nonownedwnd.mm:1040:
warning: �NSWindow� may not respond to �-backingScaleFactor�
/Users/robind/projects/buildbots/osx-10.7-vm-py2.7/build-osx-py27-2/wxWidgets/src/osx/cocoa/nonownedwnd.mm:1040:
warning: (Messages without a matching method signature
/Users/robind/projects/buildbots/osx-10.7-vm-py2.7/build-osx-py27-2/wxWidgets/src/osx/cocoa/nonownedwnd.mm:1040:
warning: will be assumed to return �id� and accept
/Users/robind/projects/buildbots/osx-10.7-vm-py2.7/build-osx-py27-2/wxWidgets/src/osx/cocoa/nonownedwnd.mm:1040:
warning: �...� as arguments.)
/Users/robind/projects/buildbots/osx-10.7-vm-py2.7/build-osx-py27-2/wxWidgets/src/osx/cocoa/nonownedwnd.mm:1040:
error: cannot convert �objc_object*� to �double� in return
make: *** [monodll_cocoa_nonownedwnd.o] Error 1
make: *** Waiting for unfinished jobs....
Error building



--
Robin Dunn
Software Craftsman
http://wxPython.org

Stefan Csomor

unread,
Jun 17, 2013, 3:33:23 PM6/17/13
to wx-...@googlegroups.com
Hi
>warning: ŒNSWindow¹ may not respond to Œ-backingScaleFactor¹
>/Users/robind/projects/buildbots/osx-10.7-vm-py2.7/build-osx-py27-2/wxWidg
>ets/src/osx/cocoa/nonownedwnd.mm:1040:
>warning: (Messages without a matching method signature

sorry, yes, I have to guard that, you need at least a 10.7 sdk in order to
be able to support retina

Thanks,

Stefan

Paul K

unread,
Jun 17, 2013, 4:05:35 PM6/17/13
to wx-...@googlegroups.com
Stefan:
 
> sorry, yes, I have to guard that, you need at least a 10.7 sdk in order to
be able to support retina
Does this mean that if I use --with-macosx-version-min=10.6 I don't get Retina support? Is it not possible to run on 10.6 and still support Retina when it's available (with the same binary)?
 
Paul.
 

Stefan Csomor

unread,
Jun 17, 2013, 4:25:36 PM6/17/13
to wx-...@googlegroups.com
Hi

> sorry, yes, I have to guard that, you need at least a 10.7 sdk in order to
be able to support retina
Does this mean that if I use --with-macosx-version-min=10.6 I don't get Retina support? Is it not possible to run on 10.6 and still support Retina when it's available (with the same binary)?

of course, you are indicating the –min version you want to be able to run on, the –max version (ie which latest features should be used if available) is indicated by the SDK you are using, that one has to be at least 10.7

Best,

Stefan

Paul K

unread,
Jun 17, 2013, 5:17:14 PM6/17/13
to wx-...@googlegroups.com
Stefan:
 
> of course, you are indicating the –min version you want to be able to run on, the –max version (ie which latest features should be used if available) is indicated by the SDK you are using, that one has to be at least 10.7
Right; I'm building on a machine with 10.7 (but I also have 10.6 available on it as well). Just to make sure I got this correctly; if I have -min set as 10.6 and -sdk pointing to 10.7 sdk, I should be able to run on 10.6 and still benefit from Retina if available on 10.7+, right?
 
--with-macosx-version-min=10.6 --with-macosx-sdk="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk"
 
Paul.

Vadim Zeitlin

unread,
Jun 17, 2013, 7:23:04 PM6/17/13
to wx-...@googlegroups.com
On Mon, 17 Jun 2013 17:52:02 +0000 Stefan Csomor wrote:

SC> >SC> bitmap, so right now this would be
SC> >SC>
SC> >SC> CreateScaled
SC> >SC> GetScaledWidth
SC> >SC> GetScaledHeight
SC> >SC> GetMagnificationFactor
SC> >SC>
SC> >SC> we need quartett of names, so it could well be
SC> >SC>
SC> >SC> CreateMagnified
SC> >SC> GetScaledWidth
SC> >SC> GetScaledHeight
SC> >SC> GetMagnificationFactor
SC> >SC>
SC> >SC> ?
SC> >
SC> > This does seem rather inconsistent :-( So we're back to CreateScaled()
SC> >and GetScaleFactor(), I guess.
SC>
SC> - what method names should I take ?

I thought you'd use

CreateScaled()
GetScaled{Width,Height,Size}()
GetScaleFactor()

It's probably confusing because I was against GetScaleFactor() initially
but I changed my mind after reading the above (hence the ":-(" which I
should have explained better, I guess): it seems like we ought to use
GetScaleFactor() even if there is some potential for confusion because
otherwise it would be inconsistent with GetScaled{Width,Height,Size}()
which really can't be called anything, AFAICS.

But now that you've added wxWindow::GetMagnificationFactor() this argument
doesn't hold water, of course... So IMO you either need to rename it to
GetScaleFactor() and use the names above or find the new names which would
be both readable and consistent with GetMagnificationFactor(). Notice that
I'm saying "you" here because I don't have any ideas, GetMagnifiedSize() is
too ugly IMNSHO and I can't think of anything else.

SC> - should I provide a
SC>
SC> common impl boilerplate code in wxBitmapBase

Yes, we definitely need some default code there just to avoid breaking the
compilation. Notice that this code is also needed in wxMSW wxBitmap
because, for unfortunate but not easy to fix, historical reasons, wxBitmap
under MSW doesn't inherit from wxBitmapBase currently (it does inherit from
wxBitmapHelpers class from which wxBitmapBase inherits as well, but I don't
think it's going to help you a lot).

SC> virtual bool CreateScaled - which would ignore the scale factor - should I
SC> assert on a diff from 1.0 ? , as it needs platform support

We do need it for portability of the code using it and it indeed should
probably just assert if the factor is != 1.0. Or maybe you create the
bitmap of size factor*(width,height) and not even make it virtual? Or does
wxOSX need something more than this done here?

Anyhow, considering that we don't have any immediate plans to ever have
factor different from 1.0 under the other platforms, I think it's fine to
just assert.

SC> virtual bool Create( .. wxDC ) which would ignore the dc

This one seems uncontroversial.

Thanks,
VZ

Christian Walther

unread,
Jun 18, 2013, 2:33:02 AM6/18/13
to wx-...@googlegroups.com
Vadim Zeitlin wrote:
> SC> - what method names should I take ?
>
> I thought you'd use
>
> CreateScaled()
> GetScaled{Width,Height,Size}()
> GetScaleFactor()
>
> It's probably confusing because I was against GetScaleFactor() initially
> but I changed my mind after reading the above (hence the ":-(" which I
> should have explained better, I guess): it seems like we ought to use
> GetScaleFactor() even if there is some potential for confusion because
> otherwise it would be inconsistent with GetScaled{Width,Height,Size}()
> which really can't be called anything, AFAICS.
>
> But now that you've added wxWindow::GetMagnificationFactor() this argument
> doesn't hold water, of course... So IMO you either need to rename it to
> GetScaleFactor() and use the names above or find the new names which would
> be both readable and consistent with GetMagnificationFactor(). Notice that
> I'm saying "you" here because I don't have any ideas, GetMagnifiedSize() is
> too ugly IMNSHO and I can't think of anything else.

I find GetScaledSize() a bit confusing because it doesn't tell me in
which of the two size units it is - scaling can go both ways.
GetMagnifiedSize() is a bit better in that regard, because it suggests
that the numbers you get from it are greater than the ones from
GetSize(), from which you can guess that it's the physical (pixel) size,
in the retina situation. How about something like
GetPixelSize()/GetPointSize() or GetPhysicalSize()/GetLogicalSize()? If
I understand correctly, the new one would be
GetPixelSize()/GetPhysicalSize(), while GetPointSize()/GetLogicalSize()
is unnecessary because that's what GetSize() does.

-Christian

Stefan Csomor

unread,
Jun 18, 2013, 6:14:27 AM6/18/13
to wx-...@googlegroups.com
Hi

>> of course, you are indicating the ­min version you want to be able to
>>run on, the ­max version (ie which latest features should be used if
>>available) is indicated by the SDK you are using, that one has to be at
>>least 10.7
>
>Right; I'm building on a machine with 10.7 (but I also have 10.6
>available on it as well). Just to make sure I got this correctly; if I
>have -min set as 10.6 and -sdk pointing to 10.7 sdk, I should be able to
>run on 10.6 and still benefit from Retina if
> available on 10.7+, right?
>
>--with-macosx-version-min=10.6
>--with-macosx-sdk="/Applications/Xcode.app/Contents/Developer/Platforms/Ma
>cOSX.platform/Developer/SDKs/MacOSX10.7.sdk"

exactly, that's how you do it

Best,

Stefan

Stefan Csomor

unread,
Jun 18, 2013, 6:40:25 AM6/18/13
to wx-...@googlegroups.com
Hi

> But now that you've added wxWindow::GetMagnificationFactor() this
>argument
>doesn't hold water, of course... So IMO you either need to rename it to
>GetScaleFactor() and use the names above or find the new names which would
>be both readable and consistent with GetMagnificationFactor(). Notice that
>I'm saying "you" here because I don't have any ideas, GetMagnifiedSize()
>is
>too ugly IMNSHO and I can't think of anything else.

if GetScaleFactor() on a window is a little bit misleading, we might
resort to the same name iOS is using: contentScaleFactor, having a
GetContentScaleFactor() on a wxWindow and GetScaleFactor on a wxBitmap
would hurt as far as consistency is concerned IMHO. What do you think ?

Best,

Stefan

Vadim Zeitlin

unread,
Jun 18, 2013, 9:09:31 AM6/18/13
to wx-...@googlegroups.com
On Tue, 18 Jun 2013 10:40:25 +0000 Stefan Csomor wrote:

SC> if GetScaleFactor() on a window is a little bit misleading, we might
SC> resort to the same name iOS is using: contentScaleFactor, having a
SC> GetContentScaleFactor() on a wxWindow and GetScaleFactor on a wxBitmap
SC> would hurt as far as consistency is concerned IMHO. What do you think ?

I'm fine with wxWindow::GetContentScaleFactor() and
wxBitmap::GetScaleFactor().


FWIW Christian's suggestion to use "physical pixel" could be a good
solution too. In this case we could have

wxWindow::GetPhysicalPixelScale()
wxBitmap::GetPhysicalPixelScale()
wxBitmap::Get{Width,Height}InPhysicalPixels()

and only the creation method has no natural name. The most descriptive
would be wxBitmap::CreateWithSizeInPhysicalPixels() but this is getting
seriously long...

Please feel free to choose whichever you prefer. As long as things are
consistent and reasonably clear/distinct from the existing methods with
"scale" in their name, it should be fine.

TIA,
VZ

David Connet

unread,
Jun 18, 2013, 9:56:10 AM6/18/13
to wx-...@googlegroups.com
Is there any place that documents what you're allowed to combine? I just
tried compiling on a 10.8 machine using 10.7 sdk, min=10.5 (xcode 4.6.2
gcc from command line) and when that bundle was run on 10.5, it crashed.
(I was using cocoa)

Or for that matter, what the min OS is allowed under compilers? I'm
thinking along the lines of Visual Studio - current versions cannot
produce win9x binaries. And VS2012 can't even do XP unless you change a
target default (which requires the VS sp)

Dave

Stefan Csomor

unread,
Jun 18, 2013, 10:44:13 AM6/18/13
to wx-...@googlegroups.com
Hi

>>>--with-macosx-version-min=10.6
>>>
>>>--with-macosx-sdk="/Applications/Xcode.app/Contents/Developer/Platforms/
>>>Ma
>>> cOSX.platform/Developer/SDKs/MacOSX10.7.sdk"
>>
>> exactly, that's how you do it
>
>Is there any place that documents what you're allowed to combine? I just
>tried compiling on a 10.8 machine using 10.7 sdk, min=10.5 (xcode 4.6.2
>gcc from command line) and when that bundle was run on 10.5, it crashed.
>(I was using cocoa)
>
>Or for that matter, what the min OS is allowed under compilers? I'm
>thinking along the lines of Visual Studio - current versions cannot
>produce win9x binaries. And VS2012 can't even do XP unless you change a
>target default (which requires the VS sp)

when using XCode you get better error messages on unsupported
combinations, when using command line builds you are more on your own, but
if you are using gcc with a -min=10.5 then this should work, what does the
crash report say ?

Best,

Stefan

David Connet

unread,
Jun 18, 2013, 12:00:38 PM6/18/13
to wx-...@googlegroups.com
From: Stefan Csomor <cso...@advancedconcepts.ch>

>>>--with-macosx-version-min=10.6
>>>
>>>--with-macosx-sdk="/Applications/Xcode.app/Contents/Developer/Platforms/
>>>Ma
>>> cOSX.platform/Developer/SDKs/MacOSX10.7.sdk"
>>
>> exactly, that's how you do it
>
>Is there any place that documents what you're allowed to combine? I just
>tried compiling on a 10.8 machine using 10.7 sdk, min=10.5 (xcode 4.6.2
>gcc from command line) and when that bundle was run on 10.5, it crashed.
>(I was using cocoa)
>
>Or for that matter, what the min OS is allowed under compilers? I'm
>thinking along the lines of Visual Studio - current versions cannot
>produce win9x binaries. And VS2012 can't even do XP unless you change a
>target default (which requires the VS sp)

SC> when using XCode you get better error messages on unsupported
SC> combinations, when using command line builds you are more on your own, but
SC> if you are using gcc with a -min=10.5 then this should work, what does the
SC> crash report say ?


I'll have to check later tonight... (that whole 'work' thing...) (just to be clear, when I said gcc, it's still xcode - I don't have a separate gcc install)

Dave

David Connet

unread,
Jun 18, 2013, 10:53:04 PM6/18/13
to wx-...@googlegroups.com
Compiled wx via makefile, used my xcode project with deployment set to
10.5 - crash report shows:
- 0 + 0
- wxStrdup(wxScopedCharTypeBuffer<wchar_t>const&) + 31
- __ZL20ConvertArgsToUnicodeiPPc + 1042
- wxEntry(int&, char**) + 47
- main + 36
- start + 53
guessing it's a null dereference

Using same wx build, and my makefiles:
- _dyld_start + 0
with a EXC_BAD_ACCESS

Guess my makefiles aren't right... (someone else crafted the
NAM/autoconfig/*.in structure for me - I barely understand it...) The
binary they generate does work correctly on the system it was built on.

Dave

William Lee

unread,
Sep 13, 2013, 12:33:05 AM9/13/13
to wx-...@googlegroups.com
Hi, I am coming across the same problem described here, was there ever a resolution?  I'm building wxWidgets from the command line but building my app in Xcode.  I'd like to support 10.5 and 10.6 but I am getting this crash.

William

Stefan Csomor

unread,
Sep 18, 2013, 1:24:53 AM9/18/13
to wx-...@googlegroups.com
Hi,

In order to have the answer also on this thread, I'm posting the
resolution from #15317 for completeness

libsystem has changed on 10.7, so r74534 must be used in order to get a
build that - while using SDKs 10.7 + - doesn't link against functions,
that don't exist in earlier versions

Best,

Stefan

-----Ursprüngliche Nachricht-----
Von: David Connet <dc...@agilityrecordbook.com>
Antworten an: "wx-...@googlegroups.com" <wx-...@googlegroups.com>
Datum: Mittwoch, 19. Juni 2013 04:53
An: "wx-...@googlegroups.com" <wx-...@googlegroups.com>
Betreff: Re: [wx-dev] Min Mac version vs sdk (was: OSX retina display -
high resolution bitmaps)
>--
>To unsubscribe, send email to wx-dev+un...@googlegroups.com
>or visit http://groups.google.com/group/wx-dev
>
>
>
>

Reply all
Reply to author
Forward
0 new messages