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.master
parent
48bb819be7
commit
3622895f09
|
|
@ -239,29 +239,37 @@ Layout.prototype.layout = function (l) {
|
||||||
// exw,exh = extra width/height available
|
// exw,exh = extra width/height available
|
||||||
switch (l.type) {
|
switch (l.type) {
|
||||||
case "h": {
|
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);
|
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 => {
|
l.c.forEach(c => {
|
||||||
c.w = c._w + ((0|c.fillx)*(l.w-l._w)/(fillx||1));
|
c.x = 0|x;
|
||||||
c.h = c.filly ? l.h - (l.pad<<1) : c._h;
|
acc_w += c._w;
|
||||||
c.x = x;
|
accfillx += 0|c.fillx;
|
||||||
c.y = l.y + (0|l.pad) + (1+(0|c.valign))*(l.h-(l.pad<<1)-c.h)/2;
|
x = acc_w + Math.floor(accfillx*(l.w-l._w)/(fillx||1));
|
||||||
x += c.w;
|
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);
|
if (c.c) this.layout(c);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "v": {
|
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);
|
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 => {
|
l.c.forEach(c => {
|
||||||
c.w = c.fillx ? l.w - (l.pad<<1) : c._w;
|
c.y = 0|y;
|
||||||
c.h = c._h + ((0|c.filly)*(l.h-l._h)/(filly||1));
|
acc_h += c._h;
|
||||||
c.y = y;
|
accfilly += 0|c.filly;
|
||||||
c.x = l.x + (0|l.pad) + (1+(0|c.halign))*(l.w-(l.pad<<1)-c.w)/2;
|
y = acc_h + Math.floor(accfilly*(l.h-l._h)/(filly||1));
|
||||||
y += c.h;
|
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);
|
if (c.c) this.layout(c);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
@ -288,8 +296,8 @@ Layout.prototype.update = function() {
|
||||||
if (l.r&1) { // rotation
|
if (l.r&1) { // rotation
|
||||||
var t = l._w;l._w=l._h;l._h=t;
|
var t = l._w;l._w=l._h;l._h=t;
|
||||||
}
|
}
|
||||||
l._w = Math.max(l._w + (l.pad<<1), 0|l.width);
|
l._w = 0|Math.max(l._w + (l.pad<<1), 0|l.width);
|
||||||
l._h = Math.max(l._h + (l.pad<<1), 0|l.height);
|
l._h = 0|Math.max(l._h + (l.pad<<1), 0|l.height);
|
||||||
}
|
}
|
||||||
var cb = {
|
var cb = {
|
||||||
"txt" : function(l) {
|
"txt" : function(l) {
|
||||||
|
|
@ -349,8 +357,8 @@ Layout.prototype.update = function() {
|
||||||
} else {
|
} else {
|
||||||
l.w = l._w;
|
l.w = l._w;
|
||||||
l.h = l._h;
|
l.h = l._h;
|
||||||
l.x = (w-l.w)/2;
|
l.x = (w-l.w)>>1;
|
||||||
l.y = y+(h-l.h)/2;
|
l.y = y+((h-l.h)>>1);
|
||||||
}
|
}
|
||||||
// layout children
|
// layout children
|
||||||
this.layout(l);
|
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