mirror of
https://github.com/belsabbagh/dotfiles.git
synced 2026-04-11 09:36:46 +00:00
quickshell and hyprland additions
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user