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

List:       cairo
Subject:    Re: Implementing HiDpi scaling
From:       Emmanuele Bassi <ebassi () gmail ! com>
Date:       2024-03-20 12:03:06
Message-ID: CALnHYQEHmvAXr3QuxHqwct0V2=tPz5a7-y+toakE5J-ea-vaRQ () mail ! gmail ! com
[Download RAW message or body]

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)]

<div dir="ltr"><div>The way &quot;high DPI&quot; 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 &quot;1&quot; and \
anything above is generally considered &quot;2&quot;. If you want to go \
into fractional scaling territory, you&#39;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>   1. device pixels, which are the physical pixels on the \
monitor</div><div>   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">https://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&#39;re exposing their information \
to other code you will need to scale them \
appropriately.<br></div><div><br></div><div>Ciao,</div><div>  \
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&#39;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 &quot;fuzzy&quot; 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&#39;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&#39;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"><br><span \
class="gmail_signature_prefix">-- </span><br><div dir="ltr" \
class="gmail_signature"><a href="https://www.bassi.io" \
target="_blank">https://www.bassi.io</a><br>[@] ebassi [@<a \
href="http://gmail.com" target="_blank">gmail.com</a>]</div>



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

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