Add Rippr source snapshot and full-history bundle

Two copies for two jobs. rippr-src/ is a browsable git archive export of
the tracked tree at 2f76983 - no build outputs, no local.properties, no
nested .git - which is convenient to read in gitea but carries no history
and will drift.

rippr-full-history.bundle is the real backup: all 18 commits, verified as
"records a complete history" and test-cloned before committing. This
matters because ~/dojo/rippr has no git remote and otherwise exists only
on one machine.

rippr-src/SNAPSHOT.md explains the difference and how to restore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 08:30:25 -05:00
parent 4debdfa518
commit 280fd7f988
106 changed files with 10377 additions and 0 deletions

View File

@@ -0,0 +1,173 @@
#!/usr/bin/env python3
"""
Emits the Android vector drawables for the chosen Route mark.
This is a real conversion, not a copy: VectorDrawable understands a subset of SVG.
Three things in the source SVG have no direct equivalent and are translated here.
<circle> -> two arc commands, since only <path> exists
stroke-dasharray -> trimPathStart / trimPathEnd, which cut one segment out of
a path; the dash offset becomes the trim start, expressed
as a fraction of the circle's circumference
opacity -> strokeAlpha / fillAlpha
Run after gen_logos.py; writes straight into app/src/main/res/drawable/.
"""
import math
import pathlib
import gen_logos
HERE = pathlib.Path(__file__).parent
RES = HERE.parent / "app" / "src" / "main" / "res" / "drawable"
CX = CY = 54.0
# The standalone logo draws its ring at r=43, which is outside the adaptive-icon safe
# circle (r=33) — a launcher mask crops it clean off, taking the accent segment with
# it. The launcher build therefore shrinks the whole mark to fit inside the safe zone.
DESIGN_RING_R = 43.0
RING_R = 32.0
GLYPH_SIZE = 40.0
# Must match concept_route() in gen_logos.py.
DASH_LEN = 34.0
DASH_OFFSET = 100.0
# Trim fractions describe an angular span, so they are derived from the design radius
# and stay correct at any ring size.
DESIGN_CIRCUMFERENCE = 2 * math.pi * DESIGN_RING_R
# Starts at due east and sweeps clockwise, matching how a browser renders <circle>,
# so the trim fractions below land the accent in the same place as the preview.
RING_PATH = (
f"M{CX + RING_R},{CY} "
f"A{RING_R},{RING_R} 0 1 1 {CX - RING_R},{CY} "
f"A{RING_R},{RING_R} 0 1 1 {CX + RING_R},{CY}"
)
LAUNCHER = """<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by design/to_vector_drawable.py — do not edit by hand. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<!-- Track ring. -->
<path
android:pathData="{ring}"
android:strokeColor="{dim}"
android:strokeWidth="3.5"
android:strokeAlpha="0.6" />
<!-- Material Symbols `route`, Apache-2.0. Scaled from its 960 box onto the icon canvas. -->
<group
android:translateX="{tx}"
android:translateY="{ty}"
android:scaleX="{scale}"
android:scaleY="{scale}">
<path
android:pathData="{glyph}"
android:fillColor="{ink}" />
</group>
<!-- Recording-progress segment: the SVG's dash pattern, cut with trimPath. -->
<path
android:pathData="{ring}"
android:strokeColor="{accent}"
android:strokeWidth="3.5"
android:strokeLineCap="round"
android:trimPathStart="{trim_start:.4f}"
android:trimPathEnd="{trim_end:.4f}" />
</vector>
"""
# Status-bar icons are flattened to a single color with only alpha preserved, so the
# ring and accent are dropped — at 24dp they would collapse into a grey smudge.
MONO = """<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by design/to_vector_drawable.py — do not edit by hand. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFFFF">
<group
android:translateX="{tx}"
android:translateY="{ty}"
android:scaleX="{scale}"
android:scaleY="{scale}">
<path
android:pathData="{glyph}"
android:fillColor="#FFFFFFFF" />
</group>
</vector>
"""
# Themed ("monochrome") launcher icons keep the 108 canvas and are tinted by the
# system, so this one keeps the ring for a fuller shape at launcher size.
THEMED = """<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by design/to_vector_drawable.py — do not edit by hand. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:pathData="{ring}"
android:strokeColor="#FF000000"
android:strokeWidth="3.5" />
<group
android:translateX="{tx}"
android:translateY="{ty}"
android:scaleX="{scale}"
android:scaleY="{scale}">
<path
android:pathData="{glyph}"
android:fillColor="#FF000000" />
</group>
</vector>
"""
def main():
glyph = gen_logos.glyph_path("route")
launcher_scale = GLYPH_SIZE / gen_logos.GLYPH_BOX
common = dict(
ring=RING_PATH,
glyph=glyph,
dim=gen_logos.DIM,
ink=gen_logos.INK,
accent=gen_logos.ACCENT,
tx=f"{CX - GLYPH_SIZE / 2:g}",
ty=f"{CY + GLYPH_SIZE / 2:g}",
scale=f"{launcher_scale:.6f}",
trim_start=DASH_OFFSET / DESIGN_CIRCUMFERENCE,
trim_end=(DASH_OFFSET + DASH_LEN) / DESIGN_CIRCUMFERENCE,
)
RES.mkdir(parents=True, exist_ok=True)
(RES / "ic_launcher_foreground.xml").write_text(LAUNCHER.format(**common))
(RES / "ic_launcher_monochrome.xml").write_text(THEMED.format(**common))
# The status-bar glyph fills a 24dp box edge to edge, minus a little padding.
mono_size = 20.0
mono_scale = mono_size / gen_logos.GLYPH_BOX
(RES / "ic_stat_rippr.xml").write_text(
MONO.format(
glyph=glyph,
tx=f"{(24 - mono_size) / 2:g}",
ty=f"{(24 + mono_size) / 2:g}",
scale=f"{mono_scale:.6f}",
)
)
for name in ("ic_launcher_foreground", "ic_launcher_monochrome", "ic_stat_rippr"):
print(f"wrote {RES / (name + '.xml')}")
if __name__ == "__main__":
main()