summaryrefslogtreecommitdiffstats
path: root/packages/dev-libs
diff options
context:
space:
mode:
authorcoast <coasteen@proton.me>2026-10-12 14:41:07 +0330
committercoast <coasteen@proton.me>2026-10-12 14:41:07 +0330
commit25922912c7e37f3bc3000e71b647e77677d8f2c5 (patch)
tree8383c5569a668613eee384ee31ea8cddc2113ee5 /packages/dev-libs
downloadexherbo-overlay-main.tar.gz
exherbo-overlay-main.tar.bz2
exherbo-overlay-main.tar.xz
exherbo-overlay-main.tar.zst
Diffstat (limited to 'packages/dev-libs')
-rw-r--r--packages/dev-libs/libbpf/libbpf-1.8.0.exheres-033
-rw-r--r--packages/dev-libs/tlottie/files/tlottie-0_pre20260911-tdesktop-compat.patch160
-rw-r--r--packages/dev-libs/tlottie/tlottie-0_pre20260911.exheres-030
3 files changed, 223 insertions, 0 deletions
diff --git a/packages/dev-libs/libbpf/libbpf-1.8.0.exheres-0 b/packages/dev-libs/libbpf/libbpf-1.8.0.exheres-0
new file mode 100644
index 0000000..9d6e2fd
--- /dev/null
+++ b/packages/dev-libs/libbpf/libbpf-1.8.0.exheres-0
@@ -0,0 +1,33 @@
+# Copyright 2026 Gurov <thuggerthugger1@duck.com>
+# Distributed under the terms of the GNU General Public License v2
+
+require github [ user=libbpf tag=v${PV} ]
+
+SUMMARY="Library for loading and managing eBPF programs"
+
+LICENCES="|| ( LGPL-2.1 BSD-2 )"
+SLOT="0"
+PLATFORMS="~amd64"
+
+DEPENDENCIES="
+ build:
+ dev-util/pkgconf
+ sys-kernel/linux-headers
+
+ build+run:
+ dev-util/elfutils
+ sys-libs/zlib
+"
+
+src_compile() {
+ emake -C src
+}
+
+src_install() {
+ emake -C src install \
+ DESTDIR="${IMAGE}" \
+ PREFIX="/usr/$(exhost --target)" \
+ LIBDIR="/usr/$(exhost --target)/lib"
+ edo rm "${IMAGE}/usr/$(exhost --target)/lib/libbpf.a"
+ emagicdocs
+}
diff --git a/packages/dev-libs/tlottie/files/tlottie-0_pre20260911-tdesktop-compat.patch b/packages/dev-libs/tlottie/files/tlottie-0_pre20260911-tdesktop-compat.patch
new file mode 100644
index 0000000..595e044
--- /dev/null
+++ b/packages/dev-libs/tlottie/files/tlottie-0_pre20260911-tdesktop-compat.patch
@@ -0,0 +1,160 @@
+diff --git a/src/composition/limits.rs b/src/composition/limits.rs
+index f8de04c..d4715ab 100644
+--- a/src/composition/limits.rs
++++ b/src/composition/limits.rs
+@@ -87,7 +87,9 @@ pub struct Limits {
+ pub max_render_points: usize,
+ /// Maximum cumulative dash output allocation estimate per frame, in bytes.
+ pub max_render_dash_bytes: usize,
+- /// Maximum geometry/raster work units charged per frame.
++ /// Maximum geometry/raster work units charged per frame. Telegram's gift
++ /// models peak near 5M (~1.25ms/frame, half of what rlottie spends on
++ /// them uncapped), so the cap keeps headroom above real content.
+ pub max_render_work: usize,
+ /// Maximum weighted pixel visits per frame at 64x64 or smaller.
+ /// Larger outputs scale this allowance proportionally to canvas area.
+@@ -140,7 +142,7 @@ impl Default for Limits {
+ max_dimension: 8192,
+ max_render_points: 1_048_576,
+ max_render_dash_bytes: 6_330_240,
+- max_render_work: 4_194_304,
++ max_render_work: 8_388_608,
+ max_render_pixels: 64 * 1024 * 1024,
+ max_render_bytes: 36 * 1024 * 1024,
+ }
+diff --git a/src/composition/parse.rs b/src/composition/parse.rs
+index 47fdaa6..4a0aac8 100644
+--- a/src/composition/parse.rs
++++ b/src/composition/parse.rs
+@@ -222,7 +222,9 @@ fn parse_vec2(c: &mut Cursor<'_>) -> Result<Vec2> {
+ match got {
+ [Some(x), Some(y)] => Ok(Vec2::new(x, y)),
+ [Some(x), None] => Ok(Vec2::new(x, x)),
+- _ => Err(invalid(c, "expected [x, y]")),
++ // rlottie zero-fills a missing component, and optimized .tgs files write
++ // `[]` for every straight-line tangent; rejecting those loses the file.
++ _ => Ok(Vec2::ZERO),
+ }
+ }
+
+@@ -1060,6 +1062,14 @@ fn parse_shape_item(c: &mut Cursor<'_>, limits: &Limits) -> Result<ParsedItem> {
+
+ let mut seen = SeenFields::default();
+ let inline_group = for_each_field_until(c, |c, key| {
++ // rlottie dispatches a shape item on `ty` and Skip()s every key ahead of
++ // it, so fields authored before `ty` never reach the reference parser.
++ // Telegram's gift patterns write {"d":3,"ty":"el"} and rely on that: the
++ // ellipses keep the exporter's winding and punch holes in the body path.
++ if ty.is_none() && !matches!(key, b"ty") {
++ c.skip_value()?;
++ return Ok(false);
++ }
+ match_once!(seen, key, {
+ b"t" => {
+ grad_type = parse_f32(c)?;
+@@ -1208,9 +1218,8 @@ fn parse_shape_item(c: &mut Cursor<'_>, limits: &Limits) -> Result<ParsedItem> {
+ None => Ok(Property::Static(default)),
+ }
+ };
+- // Path direction on primitives: `d` == 3 reverses the winding. rlottie
+- // supports this too, but accidentally ignores `d` if it appears before
+- // `ty`; honor the authored field order-independently.
++ // Path direction on primitives: `d` == 3 reverses the winding, for a `d`
++ // that the field loop above accepted (it is dropped before `ty`).
+ let direction_reversed = |c: &Cursor<'_>, pos: Option<usize>| -> bool { pos.is_some_and(|p| parse_f32(&mut c.fork_at(p)).unwrap_or(1.0) == 3.0) };
+
+ match &ty {
+diff --git a/src/composition/tests/parse.rs b/src/composition/tests/parse.rs
+index abbdbba..00aceab 100644
+--- a/src/composition/tests/parse.rs
++++ b/src/composition/tests/parse.rs
+@@ -113,21 +113,29 @@ fn parses_shape_layer() {
+ }
+
+ #[test]
+-fn primitive_direction_is_order_independent() {
+- let comp = parse(
+- r#"{"fr":30,"ip":0,"op":30,"w":100,"h":100,"layers":[
+- {"ty":4,"ind":1,"ip":0,"op":30,"st":0,"ks":{},
++fn primitive_direction_before_ty_is_dropped() {
++ // rlottie dispatches on `ty` and Skip()s every key ahead of it, so a `d`
++ // written first never reaches the reference parser. Telegram's gift
++ // patterns are authored against that: {"d":3,"ty":"el"} keeps the
++ // exporter's winding so the ellipses punch holes in the body path.
++ let ellipse = |shape: &str| {
++ let json = alloc::format!(
++ r#"{{"fr":30,"ip":0,"op":30,"w":100,"h":100,"layers":[
++ {{"ty":4,"ind":1,"ip":0,"op":30,"st":0,"ks":{{}},
+ "shapes":[
+- {"d":3,"ty":"el","p":{"a":0,"k":[50,50]},"s":{"a":0,"k":[10,10]}},
+- {"ty":"fl","c":{"a":0,"k":[1,0,0,1]},"o":{"a":0,"k":100},"r":1}
+- ]}
+- ]}"#,
+- )
+- .unwrap();
+- let Some(Shape::Ellipse(ellipse)) = comp.layers[0].shapes.first() else {
+- panic!("expected ellipse");
++ {shape},
++ {{"ty":"fl","c":{{"a":0,"k":[1,0,0,1]}},"o":{{"a":0,"k":100}},"r":1}}
++ ]}}
++ ]}}"#
++ );
++ let comp = parse(&json).unwrap();
++ let Some(Shape::Ellipse(ellipse)) = comp.layers[0].shapes.first() else {
++ panic!("expected ellipse");
++ };
++ ellipse.reversed
+ };
+- assert!(ellipse.reversed);
++ assert!(!ellipse(r#"{"d":3,"ty":"el","p":{"a":0,"k":[50,50]},"s":{"a":0,"k":[10,10]}}"#));
++ assert!(ellipse(r#"{"ty":"el","p":{"a":0,"k":[50,50]},"s":{"a":0,"k":[10,10]},"d":3}"#));
+ }
+
+ #[test]
+@@ -394,6 +402,19 @@ fn inherited_keyframe_heap_budget_is_cumulative_and_preserves_end_values() {
+ }
+ }
+
++#[test]
++fn empty_tangent_points_parse_as_zero_corners() {
++ // Optimized .tgs files write `[]` for every straight-line tangent, and
++ // rlottie zero-fills a point it cannot read; rejecting them loses the
++ // whole animation (Telegram's "21_heart_white" typing sticker).
++ let json = br#"{"i":[[],[]],"o":[[],[]],"v":[[2,0],[4,0]],"c":true}"#;
++ let limits = Limits::default();
++ let path = parse_path_value(&mut Cursor::new(json.as_slice(), 128), &limits).unwrap();
++ assert_eq!(path.vertices, alloc::vec![Vec2::new(2.0, 0.0), Vec2::new(4.0, 0.0)]);
++ assert!(path.in_tangents.iter().all(|t| *t == Vec2::ZERO));
++ assert!(path.out_tangents.iter().all(|t| *t == Vec2::ZERO));
++}
++
+ #[test]
+ fn inherited_path_budget_charges_padded_tangents_before_cloning() {
+ let json = br#"[{"t":0,"s":[{"v":[[1,2],[3,4]],"i":[],"o":[]}]},{"t":1}]"#;
+@@ -412,10 +433,9 @@ fn inherited_path_budget_charges_padded_tangents_before_cloning() {
+
+ #[test]
+ fn group_walk_preserves_siblings_transforms_and_shared_limits() {
+- // Exercise both field orders and resume the parent after the child list.
++ // Resume the parent after the child list.
+ for group in [
+ r#"{"ty":"gr","it":[{"ty":"tr","p":{"k":[3,4]}},{"ty":"gr","it":[{"ty":"rc","p":{"k":[5,6]},"s":{"k":[7,8]}}]},{"ty":"el","p":{"k":[9,10]},"s":{"k":[11,12]}}]}"#,
+- r#"{"it":[{"ty":"tr","p":{"k":[3,4]}},{"it":[{"ty":"rc","p":{"k":[5,6]},"s":{"k":[7,8]}}],"ty":"gr"},{"ty":"el","p":{"k":[9,10]},"s":{"k":[11,12]}}],"ty":"gr"}"#,
+ ] {
+ let json = alloc::format!(r#"[{group},{{"ty":"fl","c":{{"k":[1,0,0,1]}}}}]"#);
+ let mut counts = ShapeCounts::default();
+@@ -440,3 +460,14 @@ fn group_walk_preserves_siblings_transforms_and_shared_limits() {
+ assert!(parse_shape_list(&mut Cursor::new(json, 128), &Limits::default(), 0, &mut ShapeCounts::default()).is_err());
+ }
+ }
++
++#[test]
++fn group_items_before_ty_are_dropped() {
++ // Same rlottie rule as primitive_direction_before_ty_is_dropped: an `it`
++ // written ahead of `ty` is skipped, so the reference walks an empty group.
++ let json = br#"[{"it":[{"ty":"el","p":{"k":[9,10]},"s":{"k":[11,12]}}],"ty":"gr"},{"ty":"fl","c":{"k":[1,0,0,1]}}]"#;
++ let mut counts = ShapeCounts::default();
++ let (shapes, _) = parse_shape_list(&mut Cursor::new(json.as_slice(), 128), &Limits::default(), 0, &mut counts).unwrap();
++ assert!(matches!(&shapes[..], [Shape::Fill(_)]));
++ assert_eq!(counts.paints, 1);
++}
diff --git a/packages/dev-libs/tlottie/tlottie-0_pre20260911.exheres-0 b/packages/dev-libs/tlottie/tlottie-0_pre20260911.exheres-0
new file mode 100644
index 0000000..faf85da
--- /dev/null
+++ b/packages/dev-libs/tlottie/tlottie-0_pre20260911.exheres-0
@@ -0,0 +1,30 @@
+# Copyright 2026 Gurov <thuggerthugger1@duck.com>
+# Distributed under the terms of the GNU General Public License v2
+
+require cargo [ rust_minimum_version=1.96.1 ]
+
+TLOTTIE_COMMIT="31f1b542f88e7b4be9a01e749920d857535fc715"
+
+SUMMARY="Rust library for rendering Lottie animations"
+HOMEPAGE="https://github.com/dkaraush/tlottie"
+DOWNLOADS="${HOMEPAGE}/archive/${TLOTTIE_COMMIT}.tar.gz -> ${PNV}.tar.gz"
+WORK="${WORKBASE}/tlottie-${TLOTTIE_COMMIT}"
+
+LICENCES="MIT"
+SLOT="0"
+PLATFORMS="~amd64"
+
+DEFAULT_SRC_PREPARE_PATCHES=( "${FILES}/${PNV}-tdesktop-compat.patch" )
+
+src_compile() {
+ ecargo rustc --frozen --release --features c-api --lib --crate-type staticlib \
+ -- --print native-static-libs
+}
+
+src_install() {
+ insinto /usr/$(exhost --target)/lib
+ doins "target/$(rust_target_arch_name)/release/libtlottie.a"
+ insinto /usr/$(exhost --target)/include/tlottie
+ doins include/tlottie.h
+ emagicdocs
+}