@maccesar/titools 2.7.2 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,58 +0,0 @@
1
- #!/usr/bin/env bash
2
- # deps.sh — detect required system tools and guide installation.
3
-
4
- check_deps() {
5
- local master="$1"
6
- local need_rsvg=0
7
- local missing=()
8
-
9
- local master_lower
10
- master_lower=$(printf '%s' "$master" | tr '[:upper:]' '[:lower:]')
11
- case "$master_lower" in
12
- *.svg) need_rsvg=1 ;;
13
- esac
14
-
15
- if ! command -v magick >/dev/null 2>&1; then
16
- missing+=("imagemagick")
17
- fi
18
-
19
- if [[ $need_rsvg -eq 1 ]] && ! command -v rsvg-convert >/dev/null 2>&1; then
20
- missing+=("librsvg")
21
- fi
22
-
23
- if [[ ${#missing[@]} -eq 0 ]]; then
24
- log_ok "All dependencies present: $(magick -version | head -1 | awk '{print $2,$3}')"
25
- [[ $need_rsvg -eq 1 ]] && log_ok "librsvg: $(rsvg-convert --version | head -1)"
26
- return 0
27
- fi
28
-
29
- log_err "Missing required tools: ${missing[*]}"
30
- echo
31
- echo "Install with one of:"
32
- local os="$(uname -s)"
33
- case "$os" in
34
- Darwin)
35
- echo " macOS: brew install ${missing[*]}"
36
- ;;
37
- Linux)
38
- if command -v apt >/dev/null 2>&1; then
39
- local apt_pkgs=()
40
- for m in "${missing[@]}"; do
41
- case "$m" in
42
- imagemagick) apt_pkgs+=("imagemagick") ;;
43
- librsvg) apt_pkgs+=("librsvg2-bin") ;;
44
- esac
45
- done
46
- echo " Ubuntu: sudo apt install ${apt_pkgs[*]}"
47
- elif command -v pacman >/dev/null 2>&1; then
48
- echo " Arch: sudo pacman -S ${missing[*]}"
49
- elif command -v dnf >/dev/null 2>&1; then
50
- echo " Fedora: sudo dnf install ${missing[*]}"
51
- fi
52
- ;;
53
- esac
54
- echo " Windows: choco install ${missing[*]}"
55
- echo
56
- echo "After installing, re-run this command."
57
- exit 1
58
- }
@@ -1,64 +0,0 @@
1
- #!/usr/bin/env bash
2
- # gen-android-adaptive.sh — produce the adaptive icon triplet (foreground +
3
- # background + monochrome) at 5 densities.
4
- #
5
- # Android adaptive icon: 108×108dp canvas, 66×66dp safe-zone.
6
- # Densities: mdpi=108px, hdpi=162, xhdpi=216, xxhdpi=324, xxxhdpi=432.
7
- #
8
- # Foreground: logo centered inside safe-zone, transparent outside.
9
- # Background: solid color (or pattern) filling the full canvas.
10
- # Monochrome: foreground silhouette in pure white with preserved alpha — Android
11
- # applies themed tint at runtime on API 31+.
12
-
13
- gen_android_adaptive() {
14
- local master="$1"
15
- local bg="$2"
16
- local padding="$3" # percent per side
17
- local res_root="$4" # e.g. /path/app/platform/android/res
18
- local mono_master="${5:-}" # optional dedicated silhouette master
19
-
20
- local densities=(mdpi hdpi xhdpi xxhdpi xxxhdpi)
21
- local sizes=(108 162 216 324 432)
22
-
23
- for i in "${!densities[@]}"; do
24
- local d="${densities[$i]}"
25
- local size="${sizes[$i]}"
26
- local inner=$(( size * (100 - 2 * padding) / 100 ))
27
- local dir="$res_root/mipmap-$d"
28
- mkdir -p "$dir"
29
-
30
- # Foreground: logo centered, padded, transparent outside
31
- magick "$master" \
32
- -resize "${inner}x${inner}" \
33
- -background none -gravity center -extent "${size}x${size}" \
34
- -strip \
35
- "$dir/ic_launcher_foreground.png"
36
-
37
- # Background: solid color
38
- magick -size "${size}x${size}" "xc:$bg" \
39
- -strip \
40
- "$dir/ic_launcher_background.png"
41
-
42
- # Monochrome: white silhouette with alpha. If a dedicated mono master was
43
- # provided, render it fresh with the same padding. Otherwise derive from
44
- # the colored foreground (naive whitening — may flatten complex logos).
45
- if [[ -n "$mono_master" ]]; then
46
- magick "$mono_master" \
47
- -resize "${inner}x${inner}" \
48
- -background none -gravity center -extent "${size}x${size}" \
49
- -channel RGB -fill white -colorize 100 +channel \
50
- -strip \
51
- "$dir/ic_launcher_monochrome.png"
52
- else
53
- magick "$dir/ic_launcher_foreground.png" \
54
- -channel RGB -fill white -colorize 100 +channel \
55
- -strip \
56
- "$dir/ic_launcher_monochrome.png"
57
- fi
58
- done
59
-
60
- # anydpi-v26 binder directory (XML copied by caller from assets/ic_launcher.xml)
61
- mkdir -p "$res_root/mipmap-anydpi-v26"
62
-
63
- log_ok "Adaptive icons: foreground + background + monochrome × 5 densities"
64
- }
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env bash
2
- # gen-android-legacy.sh — produce the flat ic_launcher.png for pre-adaptive Android
3
- # (API 21–25, ~3% of users in 2026). Composites foreground over background and
4
- # scales down to the legacy density sizes.
5
- #
6
- # Legacy densities: mdpi=48px, hdpi=72, xhdpi=96, xxhdpi=144, xxxhdpi=192.
7
-
8
- gen_android_legacy() {
9
- local master="$1"
10
- local bg="$2"
11
- local padding="$3"
12
- local res_root="$4"
13
-
14
- local densities=(mdpi hdpi xhdpi xxhdpi xxxhdpi)
15
- local sizes=(48 72 96 144 192)
16
-
17
- for i in "${!densities[@]}"; do
18
- local d="${densities[$i]}"
19
- local size="${sizes[$i]}"
20
- # Legacy icons are displayed as-drawn (no adaptive mask), so we can fill more of
21
- # the canvas. Reduce the padding by ~40% for the legacy composite.
22
- local legacy_padding=$(( padding * 60 / 100 ))
23
- local inner=$(( size * (100 - 2 * legacy_padding) / 100 ))
24
- local dir="$res_root/mipmap-$d"
25
- mkdir -p "$dir"
26
-
27
- # Compose: solid bg + logo centered
28
- magick -size "${size}x${size}" "xc:$bg" \
29
- \( "$master" -resize "${inner}x${inner}" \) \
30
- -gravity center -composite \
31
- -strip \
32
- "$dir/ic_launcher.png"
33
- done
34
-
35
- log_ok "Legacy ic_launcher.png × 5 densities (fallback for Android <8)"
36
- }
@@ -1,46 +0,0 @@
1
- #!/usr/bin/env bash
2
- # gen-ios.sh — produce Titanium's two root-level iOS/Android icons:
3
- #
4
- # DefaultIcon.png 1024×1024, alpha preserved (universal / Android source)
5
- # DefaultIcon-ios.png 1024×1024, alpha flattened over bg-color (iOS)
6
- #
7
- # This matches what `titanium` / `alloy new` ships out of the box: a fresh
8
- # Alloy project contains both files in the project root, with DefaultIcon.png
9
- # keeping transparency and DefaultIcon-ios.png flattened (Apple rejects alpha
10
- # on App Store icon uploads).
11
- #
12
- # Padding is purely visual breathing room — iOS app icons have no launcher
13
- # mask. Default 8% per side (logo fills 84% of the canvas), which matches
14
- # Apple's HIG aesthetic for branded wordmarks.
15
-
16
- gen_ios() {
17
- local tight="$1" # tight master (aspect-preserved, transparent bg)
18
- local bg="$2"
19
- local padding="$3" # iOS padding percent per side (default 8)
20
- local out_root="$4"
21
-
22
- mkdir -p "$out_root"
23
-
24
- local size=1024
25
- local inner=$(( size * (100 - 2 * padding) / 100 ))
26
-
27
- # DefaultIcon.png — alpha preserved (matches `ti create` default for the
28
- # universal icon source; Alloy/Android use this directly).
29
- magick "$tight" \
30
- -resize "${inner}x${inner}" \
31
- -background none -gravity center -extent "${size}x${size}" \
32
- -strip \
33
- "$out_root/DefaultIcon.png"
34
-
35
- # DefaultIcon-ios.png — flattened over bg-color. This is the file iOS
36
- # actually ships; Apple rejects alpha on App Store icon uploads.
37
- magick "$tight" \
38
- -resize "${inner}x${inner}" \
39
- -background none -gravity center -extent "${size}x${size}" \
40
- -background "$bg" -alpha remove -alpha off \
41
- -strip \
42
- "$out_root/DefaultIcon-ios.png"
43
-
44
- log_ok "DefaultIcon.png (1024×1024, ${padding}% padding, alpha preserved)"
45
- log_ok "DefaultIcon-ios.png (1024×1024, ${padding}% padding, alpha flattened over $bg)"
46
- }
@@ -1,55 +0,0 @@
1
- #!/usr/bin/env bash
2
- # gen-marketplace.sh — store-submission artwork.
3
- #
4
- # iTunesConnect.png 1024×1024 (App Store)
5
- # MarketplaceArtwork.png 512×512 (Google Play)
6
- #
7
- # Alpha handling depends on whether --bg-color was EXPLICITLY provided
8
- # (tracked via the 5th argument, `flatten`):
9
- # - flatten=0 (no --bg-color) → alpha preserved, matches `ti create` default
10
- # - flatten=1 (--bg-color X) → alpha flattened on bg-color. Prevents the
11
- # dark-mode-muddy-icon issue on Play Store
12
- # and macOS App Store when the master has
13
- # significant transparent areas.
14
- #
15
- # Uses the same --ios-padding as the iOS master (default 8%) so the three
16
- # square icons share the same visual weight.
17
-
18
- gen_marketplace() {
19
- local tight="$1"
20
- local bg="$2"
21
- local padding="$3" # ios-padding percent per side
22
- local out_root="$4"
23
- local flatten="${5:-0}" # 1 when --bg-color was explicitly provided
24
-
25
- mkdir -p "$out_root"
26
-
27
- local flatten_args=()
28
- local alpha_label="alpha"
29
- if [[ "$flatten" == "1" ]]; then
30
- flatten_args=(-background "$bg" -alpha remove -alpha off)
31
- alpha_label="flat on $bg"
32
- fi
33
-
34
- # App Store (1024²)
35
- local size_ios=1024
36
- local inner_ios=$(( size_ios * (100 - 2 * padding) / 100 ))
37
- magick "$tight" \
38
- -resize "${inner_ios}x${inner_ios}" \
39
- -background none -gravity center -extent "${size_ios}x${size_ios}" \
40
- "${flatten_args[@]}" \
41
- -strip \
42
- "$out_root/iTunesConnect.png"
43
-
44
- # Google Play (512²)
45
- local size_play=512
46
- local inner_play=$(( size_play * (100 - 2 * padding) / 100 ))
47
- magick "$tight" \
48
- -resize "${inner_play}x${inner_play}" \
49
- -background none -gravity center -extent "${size_play}x${size_play}" \
50
- "${flatten_args[@]}" \
51
- -strip \
52
- "$out_root/MarketplaceArtwork.png"
53
-
54
- log_ok "Marketplace artwork: iTunesConnect.png (1024², ${padding}% padding, ${alpha_label}), MarketplaceArtwork.png (512², ${padding}% padding, ${alpha_label})"
55
- }
@@ -1,46 +0,0 @@
1
- #!/usr/bin/env bash
2
- # gen-notification.sh — white-on-transparent notification icons at 5 densities.
3
- # Android applies a runtime tint based on the notification's color property, so
4
- # all non-transparent pixels become white and color information is discarded.
5
- #
6
- # Sizes per Android spec: mdpi=24px, hdpi=36, xhdpi=48, xxhdpi=72, xxxhdpi=96.
7
- #
8
- # Notification icons are NOT masked by the launcher, so they render as drawn.
9
- # We trim any transparent padding baked into the master first, then scale the
10
- # logo to fill the canvas edge-to-edge on its longer axis (with a 1px
11
- # anti-aliasing margin per side). This matches what first-party Android apps
12
- # ship (Gmail, Slack, Chrome) — the logo reaches the edge instead of sitting
13
- # in a visibly padded box in the status bar.
14
- #
15
- # Material's 22dp-inside-24dp "live area" is a conservative guideline; in
16
- # practice notification icons benefit from going closer to the edge because
17
- # the status bar is already tiny.
18
-
19
- gen_notification() {
20
- local master="$1"
21
- local res_root="$2"
22
-
23
- local densities=(mdpi hdpi xhdpi xxhdpi xxxhdpi)
24
- local sizes=(24 36 48 72 96)
25
-
26
- for i in "${!densities[@]}"; do
27
- local d="${densities[$i]}"
28
- local size="${sizes[$i]}"
29
- # Edge-to-edge with a 1px anti-aliasing margin per side.
30
- local inner=$(( size - 2 ))
31
- (( inner < 1 )) && inner=1
32
- local dir="$res_root/drawable-$d"
33
- mkdir -p "$dir"
34
-
35
- # Trim baked-in transparent padding from the master, then scale to inner.
36
- magick "$master" \
37
- -trim +repage \
38
- -resize "${inner}x${inner}" \
39
- -channel RGB -fill white -colorize 100 +channel \
40
- -background none -gravity center -extent "${size}x${size}" \
41
- -strip \
42
- "$dir/ic_stat_notify.png"
43
- done
44
-
45
- log_ok "Notification icons (white+alpha, edge-to-edge) × 5 densities"
46
- }
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env bash
2
- # gen-splash-icon.sh — Android 12+ SplashScreen API icon.
3
- # The spec: 288dp canvas, icon occupies the central 192dp (~67% of canvas).
4
- # The OS renders a circular mask automatically, so keep the icon transparent
5
- # outside the 192dp safe-zone.
6
- #
7
- # Densities: mdpi=288px, hdpi=432, xhdpi=576, xxhdpi=864, xxxhdpi=1152.
8
-
9
- gen_splash_icon() {
10
- local master="$1"
11
- local res_root="$2"
12
-
13
- local densities=(mdpi hdpi xhdpi xxhdpi xxxhdpi)
14
- local sizes=(288 432 576 864 1152)
15
-
16
- for i in "${!densities[@]}"; do
17
- local d="${densities[$i]}"
18
- local size="${sizes[$i]}"
19
- local inner=$(( size * 192 / 288 ))
20
- local dir="$res_root/drawable-$d"
21
- mkdir -p "$dir"
22
-
23
- magick "$master" \
24
- -resize "${inner}x${inner}" \
25
- -background none -gravity center -extent "${size}x${size}" \
26
- -strip \
27
- "$dir/splash_icon.png"
28
- done
29
-
30
- log_ok "Android 12+ splash_icon.png × 5 densities"
31
- }
@@ -1,48 +0,0 @@
1
- #!/usr/bin/env bash
2
- # prepare-master.sh — produces two normalized masters from the input:
3
- #
4
- # 1. <out>_square.png — 1024×1024 PNG with the logo centered in a square
5
- # canvas and transparent padding added to sides (or top/bottom) to keep
6
- # the logo's aspect intact. Used for iOS DefaultIcon and marketplace
7
- # artwork — platforms that require square icons.
8
- #
9
- # 2. <out>_tight.png — logo rasterized at 1024-px max dimension with its
10
- # native aspect preserved (no padding added). Used for Android adaptive
11
- # icon generation so a horizontal wordmark can fill the safe-zone by
12
- # width instead of being double-padded inside the square master.
13
- #
14
- # The skill's main script passes <out>_square.png to iOS generators and
15
- # <out>_tight.png to Android adaptive/legacy/notification/splash generators.
16
-
17
- prepare_master() {
18
- local input="$1"
19
- local base="$2" # e.g. /path/.ti-branding/_master (no extension)
20
- local square="${base}_square.png"
21
- local tight="${base}_tight.png"
22
- local ext="${input##*.}"
23
- ext=$(printf '%s' "$ext" | tr '[:upper:]' '[:lower:]')
24
-
25
- mkdir -p "$(dirname "$base")"
26
-
27
- case "$ext" in
28
- svg)
29
- # Rasterize SVG at 2048-px max dimension preserving native aspect — this
30
- # is the tight master. rsvg-convert's -a flag preserves aspect when both
31
- # -w and -h are supplied, producing the larger of the two dimensions.
32
- rsvg-convert -w 2048 -h 2048 -a "$input" -o "$tight.2x.png"
33
- magick "$tight.2x.png" -resize "1024x1024>" -strip "$tight"
34
- rm -f "$tight.2x.png"
35
- ;;
36
- png)
37
- magick "$input" -resize "1024x1024>" -strip "$tight"
38
- ;;
39
- esac
40
-
41
- # Build the square master by padding the tight master to 1024×1024 with
42
- # transparency. magick's -gravity center + -extent centers the logo and
43
- # distributes padding to whichever axis is shorter.
44
- magick "$tight" \
45
- -background none -gravity center -extent 1024x1024 \
46
- -strip \
47
- "$square"
48
- }
@@ -1,67 +0,0 @@
1
- #!/usr/bin/env bash
2
- # validate.sh — sanity-check the master input.
3
-
4
- validate_master() {
5
- local master="$1"
6
- local ext="${master##*.}"
7
- ext=$(printf '%s' "$ext" | tr '[:upper:]' '[:lower:]')
8
-
9
- case "$ext" in
10
- svg)
11
- validate_svg "$master"
12
- ;;
13
- png)
14
- validate_png "$master"
15
- ;;
16
- *)
17
- log_err "Unsupported format: .$ext (expected .svg or .png)"
18
- exit 2
19
- ;;
20
- esac
21
- }
22
-
23
- validate_svg() {
24
- local master="$1"
25
- if ! grep -q "<svg" "$master" 2>/dev/null; then
26
- log_err "File does not appear to be valid SVG: $master"
27
- exit 2
28
- fi
29
-
30
- if grep -qE '<(script|foreignObject)' "$master" 2>/dev/null; then
31
- log_warn "SVG contains <script> or <foreignObject> — may not render correctly."
32
- fi
33
-
34
- log_ok "SVG input accepted (will rasterize to 1024×1024)"
35
- }
36
-
37
- validate_png() {
38
- local master="$1"
39
- local w h
40
- w=$(magick identify -format "%w" "$master" 2>/dev/null || echo 0)
41
- h=$(magick identify -format "%h" "$master" 2>/dev/null || echo 0)
42
-
43
- if [[ -z "$w" || "$w" -eq 0 ]]; then
44
- log_err "Could not read PNG dimensions: $master"
45
- exit 2
46
- fi
47
-
48
- if [[ "$w" -lt 1024 || "$h" -lt 1024 ]]; then
49
- log_err "PNG too small: ${w}×${h}. Need at least 1024×1024 for high-density output."
50
- exit 2
51
- fi
52
-
53
- if [[ "$w" -ne "$h" ]]; then
54
- log_warn "PNG is not square (${w}×${h}). Will be center-cropped to square."
55
- fi
56
-
57
- local has_alpha
58
- has_alpha=$(magick identify -format "%A" "$master" 2>/dev/null)
59
- case "$has_alpha" in
60
- True|Blend)
61
- log_ok "PNG ${w}×${h} with alpha — good for monochrome layer"
62
- ;;
63
- *)
64
- log_warn "PNG ${w}×${h} has no alpha — monochrome layer will be a square silhouette"
65
- ;;
66
- esac
67
- }