mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-10 05:03:28 -04:00
refactor(framemode): connected surfaces
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
.pragma library
|
||||
|
||||
function _number(value, fallback) {
|
||||
var n = Number(value);
|
||||
return isNaN(n) ? fallback : n;
|
||||
}
|
||||
|
||||
function snap(value, dpr) {
|
||||
var scale = dpr || 1;
|
||||
return Math.round(_number(value, 0) * scale) / scale;
|
||||
}
|
||||
|
||||
function isHorizontal(side) {
|
||||
return side === "top" || side === "bottom";
|
||||
}
|
||||
|
||||
function isVertical(side) {
|
||||
return side === "left" || side === "right";
|
||||
}
|
||||
|
||||
function bodyRect(descriptor, dpr) {
|
||||
var source = descriptor && descriptor.bodyRect ? descriptor.bodyRect : descriptor || {};
|
||||
return {
|
||||
"x": snap(source.x !== undefined ? source.x : source.bodyX, dpr),
|
||||
"y": snap(source.y !== undefined ? source.y : source.bodyY, dpr),
|
||||
"width": Math.max(0, snap(source.width !== undefined ? source.width : source.bodyW, dpr)),
|
||||
"height": Math.max(0, snap(source.height !== undefined ? source.height : source.bodyH, dpr))
|
||||
};
|
||||
}
|
||||
|
||||
function animatedBodyRect(descriptor, dpr) {
|
||||
var rect = bodyRect(descriptor, dpr);
|
||||
var offset = descriptor && descriptor.animationOffset ? descriptor.animationOffset : descriptor || {};
|
||||
var side = descriptor && descriptor.barSide ? descriptor.barSide : "bottom";
|
||||
var dx = isVertical(side) ? Math.max(-rect.width, Math.min(_number(offset.x !== undefined ? offset.x : offset.animX, 0), rect.width)) : 0;
|
||||
var dy = isHorizontal(side) ? Math.max(-rect.height, Math.min(_number(offset.y !== undefined ? offset.y : offset.animY, 0), rect.height)) : 0;
|
||||
|
||||
return {
|
||||
"x": snap(rect.x + (side === "right" ? dx : 0), dpr),
|
||||
"y": snap(rect.y + (side === "bottom" ? dy : 0), dpr),
|
||||
"width": Math.max(0, snap(rect.width - Math.abs(dx), dpr)),
|
||||
"height": Math.max(0, snap(rect.height - Math.abs(dy), dpr)),
|
||||
"dx": snap(dx, dpr),
|
||||
"dy": snap(dy, dpr)
|
||||
};
|
||||
}
|
||||
|
||||
function translatedBodyRect(descriptor, dpr) {
|
||||
var rect = bodyRect(descriptor, dpr);
|
||||
var offset = descriptor && descriptor.animationOffset ? descriptor.animationOffset : {};
|
||||
return {
|
||||
"x": snap(rect.x + _number(offset.x, 0), dpr),
|
||||
"y": snap(rect.y + _number(offset.y, 0), dpr),
|
||||
"width": rect.width,
|
||||
"height": rect.height
|
||||
};
|
||||
}
|
||||
|
||||
function connectorRadii(descriptor, rect, connectedRadius, surfaceRadius, dpr, nearIncludesSurface) {
|
||||
var side = descriptor && descriptor.barSide ? descriptor.barSide : "bottom";
|
||||
var horizontal = isHorizontal(side);
|
||||
var extent = horizontal ? rect.height : rect.width;
|
||||
var crossSize = horizontal ? rect.width : rect.height;
|
||||
var nearLimit = nearIncludesSurface ? Math.min(connectedRadius, surfaceRadius, extent, crossSize / 2) : Math.min(connectedRadius, extent, crossSize / 2);
|
||||
var farLimit = Math.min(connectedRadius, surfaceRadius, crossSize / 2);
|
||||
var near = snap(Math.max(0, nearLimit), dpr);
|
||||
var far = snap(Math.max(0, farLimit), dpr);
|
||||
var omitStart = !!(descriptor && descriptor.omitStartConnector);
|
||||
var omitEnd = !!(descriptor && descriptor.omitEndConnector);
|
||||
return {
|
||||
"near": near,
|
||||
"far": far,
|
||||
"start": omitStart ? 0 : near,
|
||||
"end": omitEnd ? 0 : near,
|
||||
"farStart": omitStart ? far : 0,
|
||||
"farEnd": omitEnd ? far : 0,
|
||||
"farExtent": Math.max(omitStart ? far : 0, omitEnd ? far : 0)
|
||||
};
|
||||
}
|
||||
|
||||
function _connectorWidth(side, spacing, radius) {
|
||||
return isVertical(side) ? spacing + radius : radius;
|
||||
}
|
||||
|
||||
function _connectorHeight(side, spacing, radius) {
|
||||
return isVertical(side) ? radius : spacing + radius;
|
||||
}
|
||||
|
||||
function connectorRect(side, rect, placement, spacing, radius, dpr) {
|
||||
var width = _connectorWidth(side, spacing, radius);
|
||||
var height = _connectorHeight(side, spacing, radius);
|
||||
var seamX = isVertical(side) ? (side === "left" ? rect.x : rect.x + rect.width) : (placement === "left" ? rect.x : rect.x + rect.width);
|
||||
var seamY = side === "top" ? rect.y : (side === "bottom" ? rect.y + rect.height : (placement === "left" ? rect.y : rect.y + rect.height));
|
||||
var x = isVertical(side) ? (side === "left" ? seamX : seamX - width) : (placement === "left" ? seamX - width : seamX);
|
||||
var y = side === "top" ? seamY : (side === "bottom" ? seamY - height : (placement === "left" ? seamY - height : seamY));
|
||||
return {
|
||||
"x": snap(x, dpr),
|
||||
"y": snap(y, dpr),
|
||||
"width": Math.max(0, snap(width, dpr)),
|
||||
"height": Math.max(0, snap(height, dpr))
|
||||
};
|
||||
}
|
||||
|
||||
function farConnectorRect(side, rect, placement, radius, dpr) {
|
||||
var x;
|
||||
var y;
|
||||
if (isHorizontal(side)) {
|
||||
x = placement === "left" ? rect.x : rect.x + rect.width - radius;
|
||||
y = side === "top" ? rect.y + rect.height : rect.y - radius;
|
||||
} else {
|
||||
x = side === "left" ? rect.x + rect.width : rect.x - radius;
|
||||
y = placement === "left" ? rect.y : rect.y + rect.height - radius;
|
||||
}
|
||||
return {
|
||||
"x": snap(x, dpr),
|
||||
"y": snap(y, dpr),
|
||||
"width": Math.max(0, snap(radius, dpr)),
|
||||
"height": Math.max(0, snap(radius, dpr))
|
||||
};
|
||||
}
|
||||
|
||||
function farBodyCapRect(side, rect, placement, radius, dpr) {
|
||||
var x;
|
||||
var y;
|
||||
if (isHorizontal(side)) {
|
||||
x = placement === "left" ? rect.x : rect.x + rect.width - radius;
|
||||
y = side === "top" ? rect.y + rect.height - radius : rect.y;
|
||||
} else {
|
||||
x = side === "left" ? rect.x + rect.width - radius : rect.x;
|
||||
y = placement === "left" ? rect.y : rect.y + rect.height - radius;
|
||||
}
|
||||
return {
|
||||
"x": snap(x, dpr),
|
||||
"y": snap(y, dpr),
|
||||
"width": Math.max(0, snap(radius, dpr)),
|
||||
"height": Math.max(0, snap(radius, dpr))
|
||||
};
|
||||
}
|
||||
|
||||
function chromeBounds(rect, side, startRadius, endRadius, farExtent, dpr) {
|
||||
var horizontal = isHorizontal(side);
|
||||
var bodyOffsetX = horizontal ? startRadius : (side === "right" ? farExtent : 0);
|
||||
var bodyOffsetY = horizontal ? (side === "bottom" ? farExtent : 0) : startRadius;
|
||||
return {
|
||||
"x": snap(rect.x - bodyOffsetX, dpr),
|
||||
"y": snap(rect.y - bodyOffsetY, dpr),
|
||||
"width": Math.max(0, snap(horizontal ? rect.width + startRadius + endRadius : rect.width + farExtent, dpr)),
|
||||
"height": Math.max(0, snap(horizontal ? rect.height + farExtent : rect.height + startRadius + endRadius, dpr)),
|
||||
"bodyOffsetX": snap(bodyOffsetX, dpr),
|
||||
"bodyOffsetY": snap(bodyOffsetY, dpr)
|
||||
};
|
||||
}
|
||||
|
||||
function fillBounds(rect, side, seamOverlap, dpr) {
|
||||
var overlapX = isHorizontal(side) ? seamOverlap : 0;
|
||||
var overlapY = isVertical(side) ? seamOverlap : 0;
|
||||
return {
|
||||
"x": snap(rect.x - overlapX, dpr),
|
||||
"y": snap(rect.y - overlapY, dpr),
|
||||
"width": Math.max(0, snap(rect.width + overlapX * 2, dpr)),
|
||||
"height": Math.max(0, snap(rect.height + overlapY * 2, dpr))
|
||||
};
|
||||
}
|
||||
|
||||
function clipEnvelope(rect, side, radii, seamOverlap, dpr) {
|
||||
var fill = fillBounds(rect, side, seamOverlap, dpr);
|
||||
var chrome = chromeBounds(fill, side, radii.start, radii.end, radii.farExtent, dpr);
|
||||
return {
|
||||
"x": chrome.x,
|
||||
"y": chrome.y,
|
||||
"width": chrome.width,
|
||||
"height": chrome.height,
|
||||
"bodyX": snap(fill.x - chrome.x, dpr),
|
||||
"bodyY": snap(fill.y - chrome.y, dpr),
|
||||
"bodyWidth": fill.width,
|
||||
"bodyHeight": fill.height
|
||||
};
|
||||
}
|
||||
|
||||
function blurRegions(descriptor, rect, radii, dpr) {
|
||||
var side = descriptor.barSide;
|
||||
var regions = [bodyRect(rect, dpr)];
|
||||
if (radii.start > 0)
|
||||
regions.push(connectorRect(side, rect, "left", 0, radii.start, dpr));
|
||||
if (radii.end > 0)
|
||||
regions.push(connectorRect(side, rect, "right", 0, radii.end, dpr));
|
||||
if (radii.farStart > 0) {
|
||||
regions.push(farConnectorRect(side, rect, "left", radii.farStart, dpr));
|
||||
regions.push(farBodyCapRect(side, rect, "left", radii.farStart, dpr));
|
||||
}
|
||||
if (radii.farEnd > 0) {
|
||||
regions.push(farConnectorRect(side, rect, "right", radii.farEnd, dpr));
|
||||
regions.push(farBodyCapRect(side, rect, "right", radii.farEnd, dpr));
|
||||
}
|
||||
return regions;
|
||||
}
|
||||
|
||||
function unionBounds(rects, padding, dpr) {
|
||||
var minX = Infinity;
|
||||
var minY = Infinity;
|
||||
var maxX = -Infinity;
|
||||
var maxY = -Infinity;
|
||||
for (var i = 0; i < rects.length; i++) {
|
||||
var rect = rects[i];
|
||||
if (!rect || rect.width <= 0 || rect.height <= 0)
|
||||
continue;
|
||||
minX = Math.min(minX, rect.x);
|
||||
minY = Math.min(minY, rect.y);
|
||||
maxX = Math.max(maxX, rect.x + rect.width);
|
||||
maxY = Math.max(maxY, rect.y + rect.height);
|
||||
}
|
||||
if (minX === Infinity)
|
||||
return {"x": 0, "y": 0, "width": 0, "height": 0};
|
||||
var pad = Math.max(0, _number(padding, 0));
|
||||
return {
|
||||
"x": snap(minX - pad, dpr),
|
||||
"y": snap(minY - pad, dpr),
|
||||
"width": Math.max(0, snap(maxX - minX + pad * 2, dpr)),
|
||||
"height": Math.max(0, snap(maxY - minY + pad * 2, dpr))
|
||||
};
|
||||
}
|
||||
|
||||
function shadowSourceBounds(descriptor, rect, radii, padding, dpr) {
|
||||
return unionBounds(blurRegions(descriptor, rect, radii, dpr), padding, dpr);
|
||||
}
|
||||
|
||||
function stableEqual(a, b, dpr) {
|
||||
if (!a || !b)
|
||||
return false;
|
||||
var threshold = 0.5 / (dpr || 1);
|
||||
return Math.abs(a.x - b.x) < threshold && Math.abs(a.y - b.y) < threshold && Math.abs(a.width - b.width) < threshold && Math.abs(a.height - b.height) < threshold;
|
||||
}
|
||||
Reference in New Issue
Block a user