quickshell and hyprland additions

This commit is contained in:
2026-03-15 13:56:00 +02:00
parent c9c27d1554
commit 1ad06b82a6
509 changed files with 68371 additions and 19 deletions

View File

@@ -0,0 +1,192 @@
.pragma library
.import "cubic.js" as Cubic
.import "point.js" as Point
.import "feature-mapping.js" as FeatureMapping
.import "utils.js" as Utils
.import "feature.js" as Feature
class MeasuredPolygon {
constructor(measurer, features, cubics, outlineProgress) {
this.measurer = measurer
this.features = features
this.outlineProgress = outlineProgress
this.cubics = []
const measuredCubics = []
let startOutlineProgress = 0
for(let i = 0; i < cubics.length; i++) {
if ((outlineProgress[i + 1] - outlineProgress[i]) > Utils.DistanceEpsilon) {
measuredCubics.push(
new MeasuredCubic(this, cubics[i], startOutlineProgress, outlineProgress[i + 1])
)
// The next measured cubic will start exactly where this one ends.
startOutlineProgress = outlineProgress[i + 1]
}
}
measuredCubics[measuredCubics.length - 1].updateProgressRange(measuredCubics[measuredCubics.length - 1].startOutlineProgress, 1)
this.cubics = measuredCubics
}
cutAndShift(cuttingPoint) {
if (cuttingPoint < Utils.DistanceEpsilon) return this
// Find the index of cubic we want to cut
const targetIndex = this.cubics.findIndex(it => cuttingPoint >= it.startOutlineProgress && cuttingPoint <= it.endOutlineProgress)
const target = this.cubics[targetIndex]
// Cut the target cubic.
// b1, b2 are two resulting cubics after cut
const { a: b1, b: b2 } = target.cutAtProgress(cuttingPoint)
// Construct the list of the cubics we need:
// * The second part of the target cubic (after the cut)
// * All cubics after the target, until the end + All cubics from the start, before the
// target cubic
// * The first part of the target cubic (before the cut)
const retCubics = [b2.cubic]
for(let i = 1; i < this.cubics.length; i++) {
retCubics.push(this.cubics[(i + targetIndex) % this.cubics.length].cubic)
}
retCubics.push(b1.cubic)
// Construct the array of outline progress.
// For example, if we have 3 cubics with outline progress [0 .. 0.3], [0.3 .. 0.8] &
// [0.8 .. 1.0], and we cut + shift at 0.6:
// 0. 0123456789
// |--|--/-|-|
// The outline progresses will start at 0 (the cutting point, that shifs to 0.0),
// then 0.8 - 0.6 = 0.2, then 1 - 0.6 = 0.4, then 0.3 - 0.6 + 1 = 0.7,
// then 1 (the cutting point again),
// all together: (0.0, 0.2, 0.4, 0.7, 1.0)
const retOutlineProgress = []
for (let i = 0; i < this.cubics.length + 2; i++) {
if (i === 0) {
retOutlineProgress.push(0)
} else if(i === this.cubics.length + 1) {
retOutlineProgress.push(1)
} else {
const cubicIndex = (targetIndex + i - 1) % this.cubics.length
retOutlineProgress.push(Utils.positiveModulo(this.cubics[cubicIndex].endOutlineProgress - cuttingPoint, 1))
}
}
// Shift the feature's outline progress too.
const newFeatures = []
for(let i = 0; i < this.features.length; i++) {
newFeatures.push(new FeatureMapping.ProgressableFeature(Utils.positiveModulo(this.features[i].progress - cuttingPoint, 1), this.features[i].feature))
}
// Filter out all empty cubics (i.e. start and end anchor are (almost) the same point.)
return new MeasuredPolygon(this.measurer, newFeatures, retCubics, retOutlineProgress)
}
static measurePolygon(measurer, polygon) {
const cubics = []
const featureToCubic = []
for (let featureIndex = 0; featureIndex < polygon.features.length; featureIndex++) {
const feature = polygon.features[featureIndex]
for (let cubicIndex = 0; cubicIndex < feature.cubics.length; cubicIndex++) {
if (feature instanceof Feature.Corner && cubicIndex == feature.cubics.length / 2) {
featureToCubic.push({ a: feature, b: cubics.length })
}
cubics.push(feature.cubics[cubicIndex])
}
}
const measures = [0] // Initialize with 0 like in Kotlin's scan
for (const cubic of cubics) {
const measurement = measurer.measureCubic(cubic)
if (measurement < 0) {
throw new Error("Measured cubic is expected to be greater or equal to zero")
}
const lastMeasure = measures[measures.length - 1]
measures.push(lastMeasure + measurement)
}
const totalMeasure = measures[measures.length - 1]
const outlineProgress = []
for (let i = 0; i < measures.length; i++) {
outlineProgress.push(measures[i] / totalMeasure)
}
const features = []
for (let i = 0; i < featureToCubic.length; i++) {
const ix = featureToCubic[i].b
features.push(
new FeatureMapping.ProgressableFeature(Utils.positiveModulo((outlineProgress[ix] + outlineProgress[ix + 1]) / 2, 1), featureToCubic[i].a))
}
return new MeasuredPolygon(measurer, features, cubics, outlineProgress)
}
}
class MeasuredCubic {
constructor(polygon, cubic, startOutlineProgress, endOutlineProgress) {
this.polygon = polygon
this.cubic = cubic
this.startOutlineProgress = startOutlineProgress
this.endOutlineProgress = endOutlineProgress
this.measuredSize = this.polygon.measurer.measureCubic(cubic)
}
updateProgressRange(
startOutlineProgress = this.startOutlineProgress,
endOutlineProgress = this.endOutlineProgress,
) {
this.startOutlineProgress = startOutlineProgress
this.endOutlineProgress = endOutlineProgress
}
cutAtProgress(cutOutlineProgress) {
const boundedCutOutlineProgress = Utils.coerceIn(cutOutlineProgress, this.startOutlineProgress, this.endOutlineProgress)
const outlineProgressSize = this.endOutlineProgress - this.startOutlineProgress
const progressFromStart = boundedCutOutlineProgress - this.startOutlineProgress
const relativeProgress = progressFromStart / outlineProgressSize
const t = this.polygon.measurer.findCubicCutPoint(this.cubic, relativeProgress * this.measuredSize)
const {a: c1, b: c2} = this.cubic.split(t)
return {
a: new MeasuredCubic(this.polygon, c1, this.startOutlineProgress, boundedCutOutlineProgress),
b: new MeasuredCubic(this.polygon, c2, boundedCutOutlineProgress, this.endOutlineProgress)
}
}
}
class LengthMeasurer {
constructor() {
this.segments = 3
}
measureCubic(c) {
return this.closestProgressTo(c, Number.POSITIVE_INFINITY).y
}
findCubicCutPoint(c, m) {
return this.closestProgressTo(c, m).x
}
closestProgressTo(cubic, threshold) {
let total = 0
let remainder = threshold
let prev = new Point.Point(cubic.anchor0X, cubic.anchor0Y)
for (let i = 1; i < this.segments; i++) {
const progress = i / this.segments
const point = cubic.pointOnCurve(progress)
const segment = point.minus(prev).getDistance()
if (segment >= remainder) {
return new Point.Point(progress - (1.0 - remainder / segment) / this.segments, threshold)
}
remainder -= segment
total += segment
prev = point
}
return new Point.Point(1.0, total)
}
}