~eliasnaur/gio

19 6

Conversion between Dp and Px, and float type

Christophe Meessen <meessen@cppm.in2p3.fr>
Details
Message ID
<8fd329fd-8f34-fe10-bf75-84af9435b0d2@cppm.in2p3.fr>
DKIM signature
missing
Download raw message
Hello,

I was wondering if it wouldn't be preferable to use Dp as default unit 
and float64 as parameter values for the end user GIO API.

My rationale is that Dp is the most frequent usage and float64 is 
supported by a battle tested math library and FPU. Conversion between Dp 
and Px by the user as well as between float32 and float64 introduces 
complexity in the code, a performance penalty, and is error prone.

I doubt that the current GIO API will change because it would break a 
lot of existing code. There are also use cases where working with Px as 
default units is desirable (e.g. game). Maybe there are other arguments 
against it that I overlooked.

I just wanted to share my thoughts while learning this aspect of GIO.

-- 

Bien cordialement,
Ch.Meessen
Details
Message ID
<CAFcc3FRRxajCxrJqbwkwVpwgu5yDYZ20QNL9S5OtC6sYQfM7Kg@mail.gmail.com>
In-Reply-To
<8fd329fd-8f34-fe10-bf75-84af9435b0d2@cppm.in2p3.fr> (view parent)
DKIM signature
missing
Download raw message
Hey Christophe,

> I was wondering if it wouldn't be preferable to use Dp as default unit
> and float64 as parameter values for the end user GIO API.

Which API though? Gio kinda has two logical APIs. There's the "ops"
API, where you add raw operations to an op.Ops, and there's the
"layout" API where you lay out widgets into a layout.Context and think
in terms of layout.Dimensions.

> My rationale is that Dp is the most frequent usage and float64 is
> supported by a battle tested math library and FPU. Conversion between Dp
> and Px by the user as well as between float32 and float64 introduces
> complexity in the code, a performance penalty, and is error prone.

Yes, it is cumbersome and error prone. Fundamentally, Gio has to work
with three units. DP, SP, and PX. SP are typically only used for text,
but scale differently than DP with respect to screen density. The
drawing backend code is concerned with pixels, so it makes sense to
have a lower-level API expressed in terms of pixels that we convert DP
and SP into.

So I could definitely see the argument that the default unit for the
layout API should be DP, but then it becomes tricky and error prone to
manage the times when you actually did want SP or PX at that layer. We
need some way to keep track of whether a given value is DP, SP, or PX,
and using unit.Value captures that easily at the cost of some extra
typing. Do you have any thoughts about other ways to ensure that units
don't get mixed up?

I totally see your point about float64, as there's significant pain
casting back and forth when you want to do operations from package
math. However, I believe that for Gio's use-cases the range of a
float64 is absurd overkill, and using float32 effectively halves Gio's
memory requirements and the amount of data that Gio needs to transfer
to the GPU. I don't know what the performance cost of switching to
float64 would be, nor do I know what the performance hit from casting
back and forth between float representations is, so it's hard to
conclude that one is definitely faster than the other. The results
would likely be application-dependent. I'd be curious to see some
benchmarks on this, but I think it'd be a huge effort to create them.

As for the FPU, I guess I would naively expect that all modern FPUs
support both float32 and float64 equally well. Is that not true? I
honestly don't know.

> I doubt that the current GIO API will change because it would break a
> lot of existing code. There are also use cases where working with Px as
> default units is desirable (e.g. game). Maybe there are other arguments
> against it that I overlooked.

I personally prefer that the high-level layout API force you to be
explicit about which unit you're using (via unit.Value), while the
low-level API assumes that the unit is pixels (at least until a
scaling transformation). However, I do wish we could find a more
ergonomic way to convert between them sometimes.
float32(gtx.Px(unit.Dp(5))) is pretty tedious to type.

> I just wanted to share my thoughts while learning this aspect of GIO.

Thanks! I appreciate the discussion. The API ergonomics are important,
and something we definitely want to polish as a community prior to any
stable release.

Cheers,
Chris
Details
Message ID
<CFM2FJ60JOCD.3LP7WOJWQZ2OF@themachine>
In-Reply-To
<CAFcc3FRRxajCxrJqbwkwVpwgu5yDYZ20QNL9S5OtC6sYQfM7Kg@mail.gmail.com> (view parent)
DKIM signature
missing
Download raw message
On Tue Nov 9, 2021 at 12:50, Chris Waldon wrote:
> > I doubt that the current GIO API will change because it would break a
> > lot of existing code. There are also use cases where working with Px as
> > default units is desirable (e.g. game). Maybe there are other arguments
> > against it that I overlooked.
>
> I personally prefer that the high-level layout API force you to be
> explicit about which unit you're using (via unit.Value), while the
> low-level API assumes that the unit is pixels (at least until a
> scaling transformation). However, I do wish we could find a more
> ergonomic way to convert between them sometimes.
> float32(gtx.Px(unit.Dp(5))) is pretty tedious to type.
>

A few quick thoughts.

- Can 1.18 generics be used to make add integer variants of graphics operations?
  This is a heavy-handed solution to a mere ergonomics issue, however.
- Should we add gtx.Pxf, and maybe even gtx.Dp/Sp/Dpf/Spf as shorthands for
  gtx.Px(unit.Dp(...)) and so on?

Elias
Details
Message ID
<CAFcc3FRp+SGiS0HatQRv3Fzyfr9ad9T7dN5tGAdmJEU4NZiVRg@mail.gmail.com>
In-Reply-To
<CFM2FJ60JOCD.3LP7WOJWQZ2OF@themachine> (view parent)
DKIM signature
missing
Download raw message
> A few quick thoughts.
>
> - Can 1.18 generics be used to make add integer variants of graphics operations?
>   This is a heavy-handed solution to a mere ergonomics issue, however.

I'm not certain. It would be interesting to explore.

> - Should we add gtx.Pxf, and maybe even gtx.Dp/Sp/Dpf/Spf as shorthands for
>   gtx.Px(unit.Dp(...)) and so on?

I fully support this. I'll put in a patch.
Details
Message ID
<18b1c93a-7a92-7bc3-4767-09e7d2c92331@meessen.net>
In-Reply-To
<CAFcc3FRRxajCxrJqbwkwVpwgu5yDYZ20QNL9S5OtC6sYQfM7Kg@mail.gmail.com> (view parent)
DKIM signature
missing
Download raw message
Hello Chris

I agree that the low level interface for raw op.Ops should stay in Px 
unit and float32. I’m only concerned about the end user API, the one 
that must be the most simple, efficient and stable.

You asked me what I would suggest in place of unit.Value. I suggest to 
pick the most frequently used unit as the default and use conversion 
functions for all the other types. The capability to support dynamic 
unit typing as does unit.Value has apparently limited use.

I’m not experienced enough with the use of Sp to see if it would be a 
problem. I assume that the use of Sp units is context specific (dealing 
with text). We could thus use Sp unit as the default in these context. 
There would be functions to convert from one unit to the other. Only 
three conversion functions (gtx methods) are needed.


Regarding the float64 type, I recognize that there are pro and cons.

Regarding the byte size, keep in mind that the standard image package 
uses int everywhere and they have the same size as a float64. I assume 
that the rationale to use int was because it is the default integer type 
and because it keeps overflow issue away. It is for the same reason that 
I suggest to use float64. It is the default float type considering all 
the math functions and its precision keeps rounding errors away.

In some places, a float32 would be good enough and float64 an overkill, 
but it would be convenient to use the same type everywhere to avoid any 
type conversion.

It may be considered an overkill today or expensive regarding memory 
usage or CPU performance, but what about it in ten years which I hope 
GIO will reach ?

I’m not trying to convince anybody. I just wanted to expose this 
suggestion and its arguments to make sure they are not overlooked in the 
design process.

-- 

Bien cordialement,
Ch.Meessen
Details
Message ID
<CAD1K+A++hoMvvcVQy4UG=Bm9t2_ReHzQtNPWYQNdEP598VkhGQ@mail.gmail.com>
In-Reply-To
<18b1c93a-7a92-7bc3-4767-09e7d2c92331@meessen.net> (view parent)
DKIM signature
missing
Download raw message
I'm wondering if the use of device-independent percentage-based
coordinate system (as is used in giocanvas) would be useful.


On Wed, Nov 10, 2021 at 1:04 PM Christophe Meessen
<christophe@meessen.net> wrote:
>
> Hello Chris
>
> I agree that the low level interface for raw op.Ops should stay in Px
> unit and float32. I’m only concerned about the end user API, the one
> that must be the most simple, efficient and stable.
>
> You asked me what I would suggest in place of unit.Value. I suggest to
> pick the most frequently used unit as the default and use conversion
> functions for all the other types. The capability to support dynamic
> unit typing as does unit.Value has apparently limited use.
>
> I’m not experienced enough with the use of Sp to see if it would be a
> problem. I assume that the use of Sp units is context specific (dealing
> with text). We could thus use Sp unit as the default in these context.
> There would be functions to convert from one unit to the other. Only
> three conversion functions (gtx methods) are needed.
>
>
> Regarding the float64 type, I recognize that there are pro and cons.
>
> Regarding the byte size, keep in mind that the standard image package
> uses int everywhere and they have the same size as a float64. I assume
> that the rationale to use int was because it is the default integer type
> and because it keeps overflow issue away. It is for the same reason that
> I suggest to use float64. It is the default float type considering all
> the math functions and its precision keeps rounding errors away.
>
> In some places, a float32 would be good enough and float64 an overkill,
> but it would be convenient to use the same type everywhere to avoid any
> type conversion.
>
> It may be considered an overkill today or expensive regarding memory
> usage or CPU performance, but what about it in ten years which I hope
> GIO will reach ?
>
> I’m not trying to convince anybody. I just wanted to expose this
> suggestion and its arguments to make sure they are not overlooked in the
> design process.
>
> --
>
> Bien cordialement,
> Ch.Meessen
>
Details
Message ID
<CFMVPVQN5DKW.E89P7OT7D0G7@macbog.local>
In-Reply-To
<18b1c93a-7a92-7bc3-4767-09e7d2c92331@meessen.net> (view parent)
DKIM signature
missing
Download raw message
On Wed Nov 10, 2021 at 19:04 CET, Christophe Meessen wrote:
> Hello Chris
>
> I agree that the low level interface for raw op.Ops should stay in Px 
> unit and float32. I’m only concerned about the end user API, the one 
> that must be the most simple, efficient and stable.
>
> You asked me what I would suggest in place of unit.Value. I suggest to 
> pick the most frequently used unit as the default and use conversion 
> functions for all the other types. The capability to support dynamic 
> unit typing as does unit.Value has apparently limited use.
>
> I’m not experienced enough with the use of Sp to see if it would be a 
> problem. I assume that the use of Sp units is context specific (dealing 
> with text). We could thus use Sp unit as the default in these context. 
> There would be functions to convert from one unit to the other. Only 
> three conversion functions (gtx methods) are needed.
>
>

I'm warming up to this idea of context specific default units. I agree
that the full generality of unit.Value is rarely used.

We could replace unit.Value with

package unit

type (
	Dp float32
	Sp float32
	// Px is left out because they don't need conversion and
	// because we want integer and float32 variants.
)

and then Go constants would just work:

package layout

type Inset {
	Top, Right, Bottom, Left unit.Dp
}

...

layout.Inset{Top: 5, Right: 10 ...}.Layout(...)

or

widget.Label{}.Layout(gtx, shaper, font, 25, "Text sized in sps").

Context would have to adjust:

// Dp converts a value in dp units to an integer pixel value.
func (c Context) Dp(v unit.Dp) int

// Dp converts a value in dp units to pixels.
func (c Context) Dpf(v unit.Dp) float32

Finally, for the special cases where you want, say, a dp value where an
sp value is expected:

package unit

func (m Metric) DpToSp(v Dp) Sp

func (m Metric) SpToDp(v Sp) Dp

...

widget.Label{}.Layout(gtx, shaper, font, gtx.Metric.DpToSp(48), "Text sized in dps").

WDYT? One downside is that Go will not prevent combining an sp and dp
value through arithmetic operators.

Elias
Details
Message ID
<CAFcc3FRDb63KtsaspRceKWoXgnvtW=-NE3UsidHQqGbzLXRGEA@mail.gmail.com>
In-Reply-To
<CFMVPVQN5DKW.E89P7OT7D0G7@macbog.local> (view parent)
DKIM signature
missing
Download raw message
> WDYT? One downside is that Go will not prevent combining an sp and dp
> value through arithmetic operators.

Actually, unless I've done something wrong, it does:

https://play.golang.org/p/R9KwScMeb0c

I think this would be a nice simplification now that I've seen a
concrete proposal for it. Thanks for the sample code, and thanks
Christophe for pushing for an improvement in this area!

Cheers,
Chris
Christophe Meessen <meessen@cppm.in2p3.fr>
Details
Message ID
<50CC05C3-8BE9-4874-AA2B-0C20E3EE040A@cppm.in2p3.fr>
In-Reply-To
<CFMVPVQN5DKW.E89P7OT7D0G7@macbog.local> (view parent)
DKIM signature
missing
Download raw message
Hello Elias, that would definitively simplify the API for the user.

It implies that we would also have to define the Point and Rectangle with the different unit types (e.g. f32.PointDp, f32.RectangleDp). Would that be acceptable ? 

--
Bien cordialement,
Ch.Meessen
Details
Message ID
<CFOJNE76XNAQ.2SQYKJXW9V38S@themachine>
In-Reply-To
<50CC05C3-8BE9-4874-AA2B-0C20E3EE040A@cppm.in2p3.fr> (view parent)
DKIM signature
missing
Download raw message
On Thu Nov 11, 2021 at 14:25, Christophe Meessen wrote:
> Hello Elias, that would definitively simplify the API for the user.
>
> It implies that we would also have to define the Point and Rectangle with the different unit types (e.g. f32.PointDp, f32.RectangleDp). Would that be acceptable ? 
>

Why don't have similar types today, so why do we need them now?

Elias
Details
Message ID
<CFOJNUMEPPNB.ZZFVPBWUB4VZ@themachine>
In-Reply-To
<CAFcc3FRDb63KtsaspRceKWoXgnvtW=-NE3UsidHQqGbzLXRGEA@mail.gmail.com> (view parent)
DKIM signature
missing
Download raw message
On Thu Nov 11, 2021 at 08:17, Chris Waldon wrote:
> > WDYT? One downside is that Go will not prevent combining an sp and dp
> > value through arithmetic operators.
>
> Actually, unless I've done something wrong, it does:
>
> https://play.golang.org/p/R9KwScMeb0c
>

Yeah, duh. Thanks for clearing that up!

Elias
Details
Message ID
<CFOL92SD3NVY.2OGF5OKCG5K3W@themachine>
In-Reply-To
<CFMVPVQN5DKW.E89P7OT7D0G7@macbog.local> (view parent)
DKIM signature
missing
Download raw message
On Thu Nov 11, 2021 at 11:30, Elias Naur wrote:
> On Wed Nov 10, 2021 at 19:04 CET, Christophe Meessen wrote:
> > Hello Chris
> >
> > I agree that the low level interface for raw op.Ops should stay in Px 
> > unit and float32. I’m only concerned about the end user API, the one 
> > that must be the most simple, efficient and stable.
> >
> > You asked me what I would suggest in place of unit.Value. I suggest to 
> > pick the most frequently used unit as the default and use conversion 
> > functions for all the other types. The capability to support dynamic 
> > unit typing as does unit.Value has apparently limited use.
> >
> > I’m not experienced enough with the use of Sp to see if it would be a 
> > problem. I assume that the use of Sp units is context specific (dealing 
> > with text). We could thus use Sp unit as the default in these context. 
> > There would be functions to convert from one unit to the other. Only 
> > three conversion functions (gtx methods) are needed.
> >
> >
>
> I'm warming up to this idea of context specific default units. I agree
> that the full generality of unit.Value is rarely used.
>
> We could replace unit.Value with
>
> package unit
>
> type (
> 	Dp float32
> 	Sp float32
> 	// Px is left out because they don't need conversion and
> 	// because we want integer and float32 variants.
> )
>
> and then Go constants would just work:
>
> package layout
>
> type Inset {
> 	Top, Right, Bottom, Left unit.Dp
> }
>
> ...
>
> layout.Inset{Top: 5, Right: 10 ...}.Layout(...)
>
> or
>
> widget.Label{}.Layout(gtx, shaper, font, 25, "Text sized in sps").
>
> Context would have to adjust:
>
> // Dp converts a value in dp units to an integer pixel value.
> func (c Context) Dp(v unit.Dp) int
>
> // Dp converts a value in dp units to pixels.
> func (c Context) Dpf(v unit.Dp) float32
>
> Finally, for the special cases where you want, say, a dp value where an
> sp value is expected:
>
> package unit
>
> func (m Metric) DpToSp(v Dp) Sp
>
> func (m Metric) SpToDp(v Sp) Dp
>
> ...
>
> widget.Label{}.Layout(gtx, shaper, font, gtx.Metric.DpToSp(48), "Text sized in dps").
>
> WDYT? One downside is that Go will not prevent combining an sp and dp
> value through arithmetic operators.
>

Perhaps we start by keeping unit.Value, but make it a type parameter constraint type:

package unit

type Value interface {
	Dp | Sp
}

We could then keep gtx.Px (and Pxf) as is, and we'd be backwards
compatible with old Gio code (I think).

Then, we can convert widgets to use specific types (unit.Sp, unit.Dp) if
we'd like to shorten their typical use, without breaking compatibility.

Elias
Details
Message ID
<CAG3idScp1u4u4fb4vmj2JODFb+a2DizS7tW8N1A627UFq8Bkvg@mail.gmail.com>
In-Reply-To
<CFOL92SD3NVY.2OGF5OKCG5K3W@themachine> (view parent)
DKIM signature
missing
Download raw message
>
> Perhaps we start by keeping unit.Value, but make it a type parameter constraint type:
>
> package unit
>
> type Value interface {
>         Dp | Sp
> }
>
> We could then keep gtx.Px (and Pxf) as is, and we'd be backwards
> compatible with old Gio code (I think).
>
> Then, we can convert widgets to use specific types (unit.Sp, unit.Dp) if
> we'd like to shorten their typical use, without breaking compatibility.

Can Pxf and friends be introduced first? That would be a baby step towards
simplifying the unit handling code.

>
> Elias
Christophe Meessen <meessen@cppm.in2p3.fr>
Details
Message ID
<c25a0a31-2b3d-2da7-4b3c-e3897442d6a4@cppm.in2p3.fr>
In-Reply-To
<CFOJNE76XNAQ.2SQYKJXW9V38S@themachine> (view parent)
DKIM signature
missing
Download raw message
Le 13/11/2021 à 10:28, Elias Naur a écrit :
> On Thu Nov 11, 2021 at 14:25, Christophe Meessen wrote:
>> Hello Elias, that would definitively simplify the API for the user.
>>
>> It implies that we would also have to define the Point and Rectangle with the different unit types (e.g. f32.PointDp, f32.RectangleDp). Would that be acceptable ?
>>
> Why don't have similar types today, so why do we need them now?

The need of a Point and Rectangle with Dp or Sp unit values might appear 
with a Canvas widget.


A more fundamental question is if we should uses Px units everywhere 
with type conversion with Dp or Sp, or expose only Dp and Sp unit values 
in the end user interface ?

We currently use the former, and with Px as int and float32 in different 
location.

The later would make the end user API simpler by minimizing the 
different types of values and units the user would have to deal with. Px 
units would be for internal use only. This implies that 
layout.Dimension, Constrains and Position.Length would be in Dp units 
instead of Px units for instance. For Position.Length, the use a float64 
would be justified because the values can be big and we have to avoid 
rounding errors.

Unless the answer to the question is straightforward and the choice can 
be made immediately, I would prefer to take the time to study it to 
examine the implications of the different choice we have. Changing from 
unit.Value to unit.Dp and unit.Sp would already be a big change that 
would break user code. Giving it time shouldn't harm. In this case the 
request of Pierre Curto to add support for Pxf() now as intermediate 
step make sense.


As I already said, I would suggest to make Dp unit a float64 and the 
default in the high level end user API (layout, widgets, canvas). Px 
would be used internally only with the types int and float32 as we have 
today. The types would thus be different and avoid any confusion. The 
advantage is that float64 is the default float type for the math 
library. Gonum plot [1] made the same choice, and VG, its underlying 
graphic library, too [2]. The canvas library of de Wolf that he 
advertised here recently uses also float64 [3].

On the other hand, pathfinder use float32 for its SVG API, but they use 
rust. Fyne uses also float32.

For Sp unit, we would still need a distinct type and conversion 
functions. I don't have enough experience with text manipulation in 
GIO to evaluate the impact on user code or if this can be avoided.

The main problem with using float is with equality test due to rounding 
errors. I saw that graphic libraries that use float often provide an 
equality test function. It's not a trivial issue [4].

[1] https://github.com/gonum/plot

[2] https://github.com/gonum/plot/tree/master/vg

[3] https://github.com/tdewolff/canvas

[4] https://stackoverflow.com/a/32334103/75517

-- 
Bien cordialement,
Ch.Meessen
Details
Message ID
<CFRB1J1E6MKW.TA2JRITJ5UE4@macbog.local>
In-Reply-To
<c25a0a31-2b3d-2da7-4b3c-e3897442d6a4@cppm.in2p3.fr> (view parent)
DKIM signature
missing
Download raw message
On Sun Nov 14, 2021 at 12:19 CET, Christophe Meessen wrote:
> Le 13/11/2021 à 10:28, Elias Naur a écrit :
> > On Thu Nov 11, 2021 at 14:25, Christophe Meessen wrote:
> >> Hello Elias, that would definitively simplify the API for the user.
> >>
> >> It implies that we would also have to define the Point and Rectangle with the different unit types (e.g. f32.PointDp, f32.RectangleDp). Would that be acceptable ?
> >>
> > Why don't have similar types today, so why do we need them now?
>
> The need of a Point and Rectangle with Dp or Sp unit values might appear 
> with a Canvas widget.
>

Ok, so not a new need triggered by your idea, right? If so, we should
keep f32 units out of the present discussion.

>
> A more fundamental question is if we should uses Px units everywhere 
> with type conversion with Dp or Sp, or expose only Dp and Sp unit values 
> in the end user interface ?
>

Before public release, I wanted to get rid of px units. However, you
need device units for font hinting, where you adjust glyphs to better
line up with the underlying pixel grid.

We may be able to get rid of that use by exposing a Dp-to-Px scale to
text shaping functions. But see next paragraph.

> We currently use the former, and with Px as int and float32 in different 
> location.
>
> The later would make the end user API simpler by minimizing the 
> different types of values and units the user would have to deal with. Px 
> units would be for internal use only. This implies that 
> layout.Dimension, Constrains and Position.Length would be in Dp units 
> instead of Px units for instance. For Position.Length, the use a float64 
> would be justified because the values can be big and we have to avoid 
> rounding errors.
>

It was a deliberate decision to use integer units in package layout,
to encourage pixel-aligned widget offsets. Widgets that overlap may
result in hard to diagnose and fix conflation artifacts. My inspiration
was a Flutter issue[0].

A secondary advantage of integers is that computations are more predictable
and portable.

[0] https://github.com/flutter/flutter/issues/15035

> Unless the answer to the question is straightforward and the choice can 
> be made immediately, I would prefer to take the time to study it to 
> examine the implications of the different choice we have. Changing from 
> unit.Value to unit.Dp and unit.Sp would already be a big change that 
> would break user code. Giving it time shouldn't harm. In this case the 
> request of Pierre Curto to add support for Pxf() now as intermediate 
> step make sense.
>

Pxf should be ok to add, but we should hold off adding Dp/Sp and
variants until we have resolved whether a generic unit.Value replaces
them.

Note that you say changing unit.Value to unit.Sp/Dp is a big change. I
agree, but with a generic unit.Value the breakage seems to be small, and
we can then convert each unit.Value to specific units on a case by case
basis.

A generic unit.Value will have to wait until February, so there's plenty
of time to experiment.

>
> As I already said, I would suggest to make Dp unit a float64 and the 
> default in the high level end user API (layout, widgets, canvas). Px 
> would be used internally only with the types int and float32 as we have 
> today. The types would thus be different and avoid any confusion.

The types would already differ with my suggestion

type (
	Dp float32
	Sp float32
)

> The 
> advantage is that float64 is the default float type for the math 
> library. Gonum plot [1] made the same choice, and VG, its underlying 
> graphic library, too [2]. The canvas library of de Wolf that he 
> advertised here recently uses also float64 [3].
>
> On the other hand, pathfinder use float32 for its SVG API, but they use 
> rust. Fyne uses also float32.
>

Converting to float64 may or may not be a performance issue. float64
take up twice the amount of space, and GPU APIs don't generally support
better than float32.

Maybe it's ok to have Dp and Sp be float64 and keep package f32. I'm not
sure.

I suggest we wait and see what generics will do to package math,
specifically whether we can somehow avoid the float64 casts.

> For Sp unit, we would still need a distinct type and conversion 
> functions. I don't have enough experience with text manipulation in 
> GIO to evaluate the impact on user code or if this can be avoided.
>

Text manipulation routines all operate on pixels, so you'd only be
changing the user-facing API, I think.

> The main problem with using float is with equality test due to rounding 
> errors. I saw that graphic libraries that use float often provide an 
> equality test function. It's not a trivial issue [4].
>

There are many hazards with floating point types, equality checks are
one of them.

Elias
Christophe Meessen <meessen@cppm.in2p3.fr>
Details
Message ID
<f202fd0c-fcdb-2e2e-d7ee-dd1b7feb5c09@cppm.in2p3.fr>
In-Reply-To
<CFRB1J1E6MKW.TA2JRITJ5UE4@macbog.local> (view parent)
DKIM signature
missing
Download raw message
Hello,

Some more input for the reflection.

The Metric value is provided by the FrameEvent value. With the proposal 
to drop unit.Value, the user would thus only be able to convert between 
units in the FrameEvent processing block.

This might be a limitation for the NewWindow() function, or any value 
(widget) initialization outside of the FrameEvent block. Unless we use 
Dp everywhere. Would a user want to use Px units ? We might still need 
to convert between Dp and Sp. Is the ratio between Dp and Sp constant ? 
I have the impression that it should be a constant.


The anti-aliasing artifact reported in the flutter issue is indeed a 
problem. The perfect fix would be to render a bigger image in the 
GPU memory without anti-aliasing, and shrink the final image by 
averaging colors to generate the image to render. This is the solution 
we might most probably get in the future since shrinking can be 
hardwired. Filling of shapes may take more time but can also be 
parallelized.

The Px unit rounding may seam as a good fix in the mean time, but it 
only works for vertical and horizontal lines. The anti-aliasing artifact 
is still there with slanted lines or curves. Some transforms may also 
degrade the resulting effect. It is thus only a very imperfect solution 
which may become obsolete once the former method is generalized.

For this reason I tend to think that we should remove any Px rounding 
related "hack" from the end user API because it makes the API a little 
more complex (type conversion), inefficient (rounding), and might not be 
needed anymore in the future. We may still use it internally as long as 
needed, and remove it without affecting user code once it becomes obsolete.


I would be curious to know if it is possible to implement the former fix 
to the anti-aliasing issue now with current GPU. I have heard that this 
method has been used in some 3D image rendering engines because it 
significantly simplify implementation like with ray tracing for instance.


Bien cordialement,
Ch.Meessen
Details
Message ID
<CFX3DW9X9JX4.22TVVE5XO2XVI@macbog.local>
In-Reply-To
<f202fd0c-fcdb-2e2e-d7ee-dd1b7feb5c09@cppm.in2p3.fr> (view parent)
DKIM signature
missing
Download raw message
On Mon Nov 22, 2021 at 12:14 CET, Christophe Meessen wrote:
> Hello,
>
> Some more input for the reflection.
>
> The Metric value is provided by the FrameEvent value. With the proposal 
> to drop unit.Value, the user would thus only be able to convert between 
> units in the FrameEvent processing block.
>

Why not? Surely we can still provide the unit conversion factors in
Metric, and then Dp/Sp methods for specific conversion to pixels.

There's also my proposal to make unit.Value a generic typeset containing
unit.Dp and unit.Sp.

> This might be a limitation for the NewWindow() function, or any value 
> (widget) initialization outside of the FrameEvent block. Unless we use 
> Dp everywhere. Would a user want to use Px units ? We might still need 
> to convert between Dp and Sp. Is the ratio between Dp and Sp constant ? 
> I have the impression that it should be a constant.
>

It is mostly a constant, but only at runtime and the user may change the
font scale while a Gio program is running.

>
> The anti-aliasing artifact reported in the flutter issue is indeed a 
> problem. The perfect fix would be to render a bigger image in the 
> GPU memory without anti-aliasing, and shrink the final image by 
> averaging colors to generate the image to render. This is the solution 
> we might most probably get in the future since shrinking can be 
> hardwired. Filling of shapes may take more time but can also be 
> parallelized.
>
> The Px unit rounding may seam as a good fix in the mean time, but it 
> only works for vertical and horizontal lines. The anti-aliasing artifact 
> is still there with slanted lines or curves. Some transforms may also 
> degrade the resulting effect. It is thus only a very imperfect solution 
> which may become obsolete once the former method is generalized.
>
> For this reason I tend to think that we should remove any Px rounding 
> related "hack" from the end user API because it makes the API a little 
> more complex (type conversion), inefficient (rounding), and might not be 
> needed anymore in the future. We may still use it internally as long as 
> needed, and remove it without affecting user code once it becomes obsolete.
>

I don't agree px aligning is a hack.

Note that package layout inherently aligns widget horizontally and
vertically, if nothing else than Dimensions and Constraints describe
axis-aligned rectangles. So inter-widget conflation are unlikely to
occur.

You can certainly provoke conflation artifacts by drawing slanted lines
in a single widget, but since the widget controls all rendering it is
also in the position to avoid the artifacts. So intra/widget conflation
artifacts are also unlikely to occur in a well-designed widget.

Finally, there are other advantages to integers. Perfect portability and
easier testing are two.

>
> I would be curious to know if it is possible to implement the former fix 
> to the anti-aliasing issue now with current GPU. I have heard that this 
> method has been used in some 3D image rendering engines because it 
> significantly simplify implementation like with ray tracing for instance.
>

It's possible, but not on all devices. For example, low-end phones probably don't
have the necessary GPU horsepower to render much larger than the screen.

Elias
Details
Message ID
<00f30bd2-ed90-7815-b5eb-88cf293625c8@meessen.net>
In-Reply-To
<CFX3DW9X9JX4.22TVVE5XO2XVI@macbog.local> (view parent)
DKIM signature
missing
Download raw message
Hello,

Le 23/11/2021 à 11:37, Elias Naur a écrit :
>> On Mon Nov 22, 2021 at 12:14 CET, Christophe Meessen wrote:
>>
>> The Metric value is provided by the FrameEvent value. With the proposal
>> to drop unit.Value, the user would thus only be able to convert between
>> units in the FrameEvent processing block.
> Why not? Surely we can still provide the unit conversion factors in
> Metric, and then Dp/Sp methods for specific conversion to pixels.

Sorry, your "why not?" is confusing me. It could mean "what would be bad 
with this limitation?" or "why would there be a limitation?".

Just to be sure that I understood correctly, the Metric value is only 
accessible in the FrameEvent handler and we need the metric to do unit 
conversion. Is my current understanding correct ? I don’t know how it 
all works internally.

I overlooked that we might loose the possibility to do the conversion 
outside of the FrameEvent handler when initially suggesting to drop the 
dynamic unit.Value and use Dp as the default unit everywhere.

> There's also my proposal to make unit.Value a generic typeset containing
> unit.Dp and unit.Sp.

This new track is indeed worth to be investigated. I wait for Go1.18 to 
see how it may look like.
>> This might be a limitation for the NewWindow() function, or any value
>> (widget) initialization outside of the FrameEvent block. Unless we use
>> Dp everywhere. Would a user want to use Px units ? We might still need
>> to convert between Dp and Sp. Is the ratio between Dp and Sp constant ?
>> I have the impression that it should be a constant.
>>
> It is mostly a constant, but only at runtime and the user may change the
> font scale while a Gio program is running.

Agree, I didn’t thought of this. It would be a benefit for the 
accessibility of an application.

Changing the Dp to Sp ratio would be done at the beginning of the 
FrameEvent processing I assume. Is there another place we could do this ?


Regarding integer Px metrics, I agree that there are also positive 
arguments to use integers. There are pros and cons on both sides. It’s a 
design choice which is up to you and Chris.


-- 
Bien cordialement,
Ch.Meessen
Details
Message ID
<CG00Z3P6AURQ.1TZ8J75CRMNUI@themachine>
In-Reply-To
<00f30bd2-ed90-7815-b5eb-88cf293625c8@meessen.net> (view parent)
DKIM signature
missing
Download raw message
On Wed Nov 24, 2021 at 17:46, Christophe Meessen wrote:
> Hello,
>
> Le 23/11/2021 à 11:37, Elias Naur a écrit :
> >> On Mon Nov 22, 2021 at 12:14 CET, Christophe Meessen wrote:
> >>
> >> The Metric value is provided by the FrameEvent value. With the proposal
> >> to drop unit.Value, the user would thus only be able to convert between
> >> units in the FrameEvent processing block.
> > Why not? Surely we can still provide the unit conversion factors in
> > Metric, and then Dp/Sp methods for specific conversion to pixels.
>
> Sorry, your "why not?" is confusing me. It could mean "what would be bad 
> with this limitation?" or "why would there be a limitation?".
>
> Just to be sure that I understood correctly, the Metric value is only 
> accessible in the FrameEvent handler and we need the metric to do unit 
> conversion. Is my current understanding correct ? I don’t know how it 
> all works internally.
>

The unit.Metric is available to all code that can access the
layout.Context, which embeds unit.Metric. See [0]. Every call to
Context.Px uses that metric[1].

> >> This might be a limitation for the NewWindow() function, or any value
> >> (widget) initialization outside of the FrameEvent block. Unless we use
> >> Dp everywhere. Would a user want to use Px units ? We might still need
> >> to convert between Dp and Sp. Is the ratio between Dp and Sp constant ?
> >> I have the impression that it should be a constant.
> >>
> > It is mostly a constant, but only at runtime and the user may change the
> > font scale while a Gio program is running.
>
> Agree, I didn’t thought of this. It would be a benefit for the 
> accessibility of an application.
>
> Changing the Dp to Sp ratio would be done at the beginning of the 
> FrameEvent processing I assume. Is there another place we could do this ?
>

FrameEvents are atomic in the sense that the configuration can only
change between frames. A change to the Dp/Sp ratio happens between
frames, and triggers a FrameEvent to update the UI accordingly.

Elias

[0] https://git.sr.ht/~eliasnaur/gio/tree/main/item/layout/context.go#L23
[1] https://git.sr.ht/~eliasnaur/gio/tree/main/item/layout/context.go#L72
Details
Message ID
<CAMAFT9WCQt9_EiNyTWOE3HwC2gq=UWU+AZJNBo-EOVPprjQSXQ@mail.gmail.com>
In-Reply-To
<CG00Z3P6AURQ.1TZ8J75CRMNUI@themachine> (view parent)
DKIM signature
missing
Download raw message
I've implemented a proof-of-concept of Christophe's idea of using
specific unit types instead of unit.Value. It's in the `units` branch
and currently only run on Linux. The change also implements a more
ergonomic op.Offset and clip.RRect for fewer float32 conversions, as
well as unit.Point/Rectangle for replacing image.Point/Rectangle.

WDYT?

Elias
Reply to thread Export thread (mbox)