mirror of https://github.com/espruino/BangleApps
Layout: avoid floating point numbers
The previous approach involved calculating the width of each element independently, and deriving the `x` coordinate of each element by summing the previous widths. However, if the widths are rounded, summing them leads to accumulated rounding errors. This change effectively takes the alternate approach of calculating the `x` coordinate of each element independently, and then deriving the widths from the differences between adjacent values of `x`. As a bonus, this change corrects a couple issues in the `padding_with_fill` test.pull/829/head
parent
48bb819be7
commit
3622895f09
|
@ -239,29 +239,37 @@ Layout.prototype.layout = function (l) {
|
|||
// exw,exh = extra width/height available
|
||||
switch (l.type) {
|
||||
case "h": {
|
||||
var x = l.x + (0|l.pad);
|
||||
var acc_w = l.x + (0|l.pad);
|
||||
var accfillx = 0;
|
||||
var fillx = l.c && l.c.reduce((a,l)=>a+(0|l.fillx),0);
|
||||
if (!fillx) { x += (l.w-l._w)/2; }
|
||||
if (!fillx) { acc_w += (l.w-l._w)>>1; }
|
||||
var x = acc_w;
|
||||
l.c.forEach(c => {
|
||||
c.w = c._w + ((0|c.fillx)*(l.w-l._w)/(fillx||1));
|
||||
c.h = c.filly ? l.h - (l.pad<<1) : c._h;
|
||||
c.x = x;
|
||||
c.y = l.y + (0|l.pad) + (1+(0|c.valign))*(l.h-(l.pad<<1)-c.h)/2;
|
||||
x += c.w;
|
||||
c.x = 0|x;
|
||||
acc_w += c._w;
|
||||
accfillx += 0|c.fillx;
|
||||
x = acc_w + Math.floor(accfillx*(l.w-l._w)/(fillx||1));
|
||||
c.w = 0|(x - c.x);
|
||||
c.h = 0|(c.filly ? l.h - (l.pad<<1) : c._h);
|
||||
c.y = 0|(l.y + (0|l.pad) + ((1+(0|c.valign))*(l.h-(l.pad<<1)-c.h)>>1));
|
||||
if (c.c) this.layout(c);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "v": {
|
||||
var y = l.y + (0|l.pad);;
|
||||
var acc_h = l.y + (0|l.pad);
|
||||
var accfilly = 0;
|
||||
var filly = l.c && l.c.reduce((a,l)=>a+(0|l.filly),0);
|
||||
if (!filly) { y += (l.h-l._h)/2 }
|
||||
if (!filly) { acc_h += (l.h-l._h)>>1; }
|
||||
var y = acc_h;
|
||||
l.c.forEach(c => {
|
||||
c.w = c.fillx ? l.w - (l.pad<<1) : c._w;
|
||||
c.h = c._h + ((0|c.filly)*(l.h-l._h)/(filly||1));
|
||||
c.y = y;
|
||||
c.x = l.x + (0|l.pad) + (1+(0|c.halign))*(l.w-(l.pad<<1)-c.w)/2;
|
||||
y += c.h;
|
||||
c.y = 0|y;
|
||||
acc_h += c._h;
|
||||
accfilly += 0|c.filly;
|
||||
y = acc_h + Math.floor(accfilly*(l.h-l._h)/(filly||1));
|
||||
c.h = 0|(y - c.y);
|
||||
c.w = 0|(c.fillx ? l.w - (l.pad<<1) : c._w);
|
||||
c.x = 0|(l.x + (0|l.pad) + ((1+(0|c.halign))*(l.w-(l.pad<<1)-c.w)>>1));
|
||||
if (c.c) this.layout(c);
|
||||
});
|
||||
break;
|
||||
|
@ -288,8 +296,8 @@ Layout.prototype.update = function() {
|
|||
if (l.r&1) { // rotation
|
||||
var t = l._w;l._w=l._h;l._h=t;
|
||||
}
|
||||
l._w = Math.max(l._w + (l.pad<<1), 0|l.width);
|
||||
l._h = Math.max(l._h + (l.pad<<1), 0|l.height);
|
||||
l._w = 0|Math.max(l._w + (l.pad<<1), 0|l.width);
|
||||
l._h = 0|Math.max(l._h + (l.pad<<1), 0|l.height);
|
||||
}
|
||||
var cb = {
|
||||
"txt" : function(l) {
|
||||
|
@ -349,8 +357,8 @@ Layout.prototype.update = function() {
|
|||
} else {
|
||||
l.w = l._w;
|
||||
l.h = l._h;
|
||||
l.x = (w-l.w)/2;
|
||||
l.y = y+(h-l.h)/2;
|
||||
l.x = (w-l.w)>>1;
|
||||
l.y = y+((h-l.h)>>1);
|
||||
}
|
||||
// layout children
|
||||
this.layout(l);
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Loading…
Reference in New Issue