[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cairo
Subject:    Re: Implementing HiDpi scaling
From:       Federico Angelilli <list () fedang ! net>
Date:       2024-03-20 13:32:58
Message-ID: 65B03E28-89E7-45F5-94CE-B706BFD71919 () fedang ! net
[Download RAW message or body]

Thank you very much for the breakdown, I totally missed that cairo feature.

Am I right into thinking that the logical pixels don't need any calculation (apart from when comparing \
them to pixel information from X, like you said)? So that I just need to change the click handling and \
surface creation code

Also, should the size of the surface be (digital * ratio)? So the whole things looks like

1) get ratio from the monitor
2) create surface with size (digital * ratio)
3) set cairo device scale to (ratio)
4) write normally with digital
5) handle x11 events as (device / ratio)

Did I understood everything correctly?

Regards


On March 20, 2024 1:03:06 PM GMT+01:00, Emmanuele Bassi <ebassi@gmail.com> wrote:
> The way "high DPI" support is implemented is typically this:
> 
> - You retrieve the scaling factor from the windowing system; in the case of
> X11 you can deduce the scaling factor from the ratio between the width and
> the height of the target monitor: anything below 192 is generally
> considered "1" and anything above is generally considered "2". If you want
> to go into fractional scaling territory, you'll likely need some other
> mechanism, like a user configuration setting.
> - Once you have a scaling factor, you create a windowing system surface
> that has two units:
> 1. device pixels, which are the physical pixels on the monitor
> 2. logical pixels, which are the scaled pixels for drawing operations
> 
> Your surfaces have to be created with the size in device pixels; then you
> call cairo_surface_set_device_scale() with the scaling factor you computed:
> 
> https://www.cairographics.org/manual/cairo-cairo-surface-t.html#cairo-surface-set-device-scale
> 
> After that, every drawing operation must be in **logical** pixels, and the
> Cairo will automatically scale every coordinate and size appropriately.
> 
> It is your responsibility to deal with device and logical coordinates; for
> instance, windowing system events will be in device coordinates, but if
> you're exposing their information to other code you will need to scale them
> appropriately.
> 
> Ciao,
> Emmanuele.
> 
> On Wed, 20 Mar 2024 at 11:47, Federico Angelilli <list@fedang.net> wrote:
> 
> > Hello,
> > Sorry for the late reply.
> > 
> > I am using cairo for drawing and pango for the text. I am creating a
> > window with xcb and using cairo_xcb_surface.
> > 
> > I can easily extract the dpi information from the xrandr api calls. Now
> > that I have this ratio, I have to use it somewhere to scale my canvas
> > appropriately.
> > 
> > I will try using cairo_scale, and should I also scale the size of the
> > xcb_surface by the same ratio?
> > 
> > Anyway my main concern about antialising is that since I am making layered
> > shapes (think buttons) the border and the background will not match up
> > pixel perfect (which is something that I have seen in other project using
> > cairo).
> > 
> > Does what I described about scaling the surface makes sense or am I
> > misinterpreting cairo_scale?
> > 
> > Regards
> > 
> > Ps:
> > I will soon try and post the results
> > 
> > 
> > On March 18, 2024 1:46:54 PM GMT+01:00, Dov Grobgeld <
> > dov.grobgeld@gmail.com> wrote:
> > 
> > > I think that you should describe in detail what you expect.
> > > 
> > > In pure vector graphics a contour may cut through a pixel and partially
> > > obscure it, and it is then the responsibility of the graphics engine to
> > > create anti-aliased graphics by mixing the colors of the background and the
> > > foreground. As a user you typically don't need to concern yourself with
> > > that as it is done automatically.
> > > 
> > > However, e.g. for text this may cause "fuzzy" characters and the engine
> > > will then fallback to moving the contours and scale the font so that the
> > > glyphs fall on whole pixels.
> > > 
> > > Note that the use of anti-aliased graphics is less needed, and less
> > > visible, for an HDPI device.
> > > 
> > > In any case all that you will typically need is cairo_scale() as Uli
> > > Shlachter already described.
> > > 
> > > Try it!
> > > 
> > > Regards,
> > > 
> > > 
> > > On Sun, Mar 17, 2024 at 12:46 PM Federico Angelilli <list@fedang.net>
> > > wrote:
> > > 
> > > > Hi
> > > > 
> > > > Will cairo_scale make a pixel perfect image for non integer scales? To
> > > > my understanding the scale matrix will be multiplied to all the coordinates
> > > > scaling the coordinates appropriately. Should I also scale the whole
> > > > surface by that same factor?
> > > > 
> > > > Regards
> > > > 
> > > > 
> > > > On March 16, 2024 6:27:56 PM GMT+01:00, Uli Schlachter <psychon@znc.in>
> > > > wrote:
> > > > 
> > > > > Hi
> > > > > 
> > > > > Am 14.03.24 um 16:34 schrieb fedang:
> > > > > 
> > > > > > Hello all,
> > > > > > 
> > > > > > I am writing a small X11 app using cairo as the drawing backend. I was wondering if and how \
> > > > > > to implement fractional scaling to accommodate high dpi screens. After searching online I \
> > > > > > found almost nothing, so here I am. 
> > > > > > Can someone give me some pointers on what to do? I can get a scale factor for the screens \
> > > > > > (depending on the size) but I have no idea how to actually use it in the draw code.
> > > > > > 
> > > > > 
> > > > > I'm not sure if I understand the question. You can use cairo_scale() to set a scale factor for \
> > > > > all drawing. So I would say that you can just apply the scale factor with cairo_scale() before \
> > > > > drawing. 
> > > > > Of course, this assumes that you don't use cairo_identity_matrix() or cairo_set_matrix() in \
> > > > > your drawing. Instead, cairo_save() and cairo_restore() should be used around temporary \
> > > > > modifications of the transformations. 
> > > > > Cheers,
> > > > > Uli
> > > > > 
> > > > > 
> 
> -- 
> https://www.bassi.io
> [@] ebassi [@gmail.com]


[Attachment #3 (text/html)]

<html><head></head><body><div dir="auto">Thank you very much for the breakdown, I totally missed that \
cairo feature.<br><br>Am I right into thinking that the logical pixels don't need any calculation (apart \
from when comparing them to pixel information from X, like you said)? So that I just need to change the \
click handling and surface creation code<br><br>Also, should the size of the surface be (digital * \
ratio)? So the whole things looks like<br><br>1) get ratio from the monitor<br>2) create surface with \
size (digital * ratio)<br>3) set cairo device scale to (ratio)<br>4) write normally with digital<br>5) \
handle x11 events as (device / ratio)<br><br>Did I understood everything \
correctly?<br><br>Regards<br></div><br><br><div class="gmail_quote"><div dir="auto">On March 20, 2024 \
1:03:06 PM GMT+01:00, Emmanuele Bassi &lt;ebassi@gmail.com&gt; wrote:</div><blockquote \
class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); \
padding-left: 1ex;"> <div dir="ltr"><div>The way "high DPI" support is implemented is typically \
this:</div><div><br></div><div>- You retrieve the scaling factor from the windowing system; in the case \
of X11 you can deduce the scaling factor from the ratio between the width and the height of the target \
monitor: anything below 192 is generally considered "1" and anything above is generally considered "2". \
If you want to go into fractional scaling territory, you'll likely need some other mechanism, like a user \
configuration setting.<br></div><div>- Once you have a scaling factor, you create a windowing system \
surface that has two units:</div><div>&nbsp; 1. device pixels, which are the physical pixels on the \
monitor</div><div>&nbsp; 2. logical pixels, which are the scaled pixels for drawing \
operations</div><div><br></div><div>Your surfaces have to be created with the size in device pixels; then \
you call cairo_surface_set_device_scale() with the scaling factor you \
computed:</div><div><br></div><div><a \
href="https://www.cairographics.org/manual/cairo-cairo-surface-t.html#cairo-surface-set-device-scale">http \
s://www.cairographics.org/manual/cairo-cairo-surface-t.html#cairo-surface-set-device-scale</a></div><div><br></div><div>After \
that, every drawing operation must be in **logical** pixels, and the Cairo will automatically scale every \
coordinate and size appropriately.</div><div><br></div><div>It is your responsibility to deal with device \
and logical coordinates; for instance, windowing system events will be in device coordinates, but if \
you're exposing their information to other code you will need to scale them \
appropriately.<br></div><div><br></div><div>Ciao,</div><div>&nbsp;Emmanuele.<br></div></div><br><div \
class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 20 Mar 2024 at 11:47, Federico Angelilli \
&lt;<a href="mailto:list@fedang.net">list@fedang.net</a>&gt; wrote:<br></div><blockquote \
class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid \
rgb(204,204,204);padding-left:1ex"><div><div dir="auto">Hello,<br>Sorry for the late reply.<br><br>I am \
using cairo for drawing and pango for the text. I am creating a window with xcb and using \
cairo_xcb_surface.<br><br>I can easily extract the dpi information from the xrandr api calls. Now that I \
have this ratio, I have to use it somewhere to scale my canvas appropriately.<br><br>I will try using \
cairo_scale, and should I also scale the size of the xcb_surface by the same ratio?<br><br>Anyway my main \
concern about antialising is that since I am making layered shapes (think buttons) the border and the \
background will not match up pixel perfect (which is something that I have seen in other project using \
cairo).<br><br>Does what I described about scaling the surface makes sense or am I misinterpreting \
cairo_scale?<br><br>Regards<br><br>Ps:<br>I will soon try and post the results <br></div><br><br><div \
class="gmail_quote"><div dir="auto">On March 18, 2024 1:46:54 PM GMT+01:00, Dov Grobgeld &lt;<a \
href="mailto:dov.grobgeld@gmail.com" target="_blank">dov.grobgeld@gmail.com</a>&gt; \
wrote:</div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid \
rgb(204,204,204);padding-left:1ex"> <div dir="ltr"><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif">I think that you should describe in detail what you \
expect.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div \
class="gmail_default" style="font-family:arial,helvetica,sans-serif">In pure vector graphics a contour \
may cut through a pixel and partially obscure it, and it is then the responsibility of the graphics \
engine to create anti-aliased graphics by mixing the colors of the background and the foreground. As a \
user you typically don't need to concern yourself with that as it is done automatically.</div><div \
class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif">However, e.g. for text this may cause "fuzzy" characters \
and the engine will then fallback to moving the contours and scale the font so that the glyphs fall on \
whole pixels.</div><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif">Note that the use of anti-aliased graphics is less needed, \
and less visible, for an HDPI device.</div><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif">In any case all that you will typically need is \
cairo_scale() as Uli Shlachter already described. <br></div><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif">Try it!</div><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif">Regards,</div><div class="gmail_default" \
style="font-family:arial,helvetica,sans-serif"><br></div></div><br><div class="gmail_quote"><div \
dir="ltr" class="gmail_attr">On Sun, Mar 17, 2024 at 12:46 PM Federico Angelilli &lt;<a \
href="mailto:list@fedang.net" target="_blank">list@fedang.net</a>&gt; wrote:<br></div><blockquote \
class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid \
rgb(204,204,204);padding-left:1ex"><div><div dir="auto">Hi<br><br>Will cairo_scale make a pixel perfect \
image for non integer scales? To my understanding the scale matrix will be multiplied to all the \
coordinates scaling the coordinates appropriately. Should I also scale the whole surface by that same \
factor?<br><br>Regards</div><br><br><div class="gmail_quote"><div dir="auto">On March 16, 2024 6:27:56 PM \
GMT+01:00, Uli Schlachter &lt;<a href="mailto:psychon@znc.in" target="_blank">psychon@znc.in</a>&gt; \
wrote:</div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid \
rgb(204,204,204);padding-left:1ex"> <pre><div dir="auto">Hi<br><br>Am 14.03.24 um 16:34 schrieb \
fedang:<br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 1ex 0.8ex;border-left:1px solid \
rgb(114,159,207);padding-left:1ex"><div dir="auto">Hello all,<br><br>I am writing a small X11 app using \
cairo as the drawing backend. I was wondering if and how to implement<br>fractional scaling to \
accommodate high dpi screens. After searching online I found almost nothing, so here I am.<br><br>Can \
someone give me some pointers on what to do? I can get a scale factor for the screens (depending on the \
size)<br>but I have no idea how to actually use it in the draw code.<br></div></blockquote><div \
dir="auto"><br>I'm not sure if I understand the question. You can use cairo_scale() to set a scale factor \
for all drawing. So I would say that you can just apply the scale factor with cairo_scale() before \
drawing.<br><br>Of course, this assumes that you don't use cairo_identity_matrix() or cairo_set_matrix() \
in your drawing. Instead, cairo_save() and cairo_restore() should be used around temporary modifications \
of the transformations.<br><br>Cheers,<br>Uli<br></div></pre></blockquote></div></div></blockquote></div> \
</blockquote></div></div></blockquote></div><br clear="all"></blockquote></div></body></html>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic