Files
tobias 17dc42e645 App-Symbol: Entwurf 3 bei 54 Prozent
DataMetric oben, das CI-Fahrzeug in der Mitte, 360 in Audi-Rot unten, auf
Nacht-Grund. Ausgewaehlt aus zwoelf Varianten, jede zweimal gezeigt: gross
und bei 60 pt, der Groesse auf dem Homescreen - daran entschied es sich.

Vektorquelle unter native/logo/, erzeugt von scripts/logo-bauen.cjs. Das
Fahrzeug liest das Skript aus ICONS.audi im Panel, damit es nur eine Quelle
fuer diese Form gibt; die Schriften stecken als data-URI in der SVG, sonst
haengt das Ergebnis davon ab, welche Fonts auf dem rasternden Rechner
installiert sind.

Drei Ausfuehrungen fuer iOS 18: hell mit eigenem Grund, dunkel und getoent
ohne - dort legt das System seinen eigenen Grund darunter, ein
mitgeliefertes Schwarz bliebe als Kasten sichtbar. Getoent wertet iOS die
Helligkeit aus, deshalb wird die 360 dort ein helleres Grau statt Rot.

ios-signieren.sh legt die Vorlage ueber die von Capacitor erzeugte - ios/
ist gitignored, ein in Xcode eingesetztes Symbol waere beim naechsten
cap add ios wieder weg.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 14:43:05 +02:00

136 lines
5.6 KiB
JavaScript

/**
* Baut die drei App-Symbol-Vorlagen als SVG.
*
* Gewaehlt wurde Entwurf 3 bei 54 % Fahrzeuggroesse: DataMetric oben, das
* CI-Fahrzeug in der Mitte, 360 in Audi-Rot unten, auf Nacht-Grund.
*
* WARUM DIE SCHRIFTEN EINGEBETTET WERDEN
* --------------------------------------
* Eine SVG-Datei, die nur `font-family: "Audi Type"` nennt, sieht nur dort
* richtig aus, wo die Schrift installiert ist. Auf einem anderen Rechner - und
* in jedem Rasterisierer - faellt sie auf eine Ersatzschrift zurueck, und das
* faellt erst am fertigen Symbol auf. Die woff2-Dateien stecken deshalb als
* data:-URI in der Datei; sie ist damit fuer sich allein vollstaendig.
*
* DIE DREI AUSFUEHRUNGEN VON iOS 18
* ---------------------------------
* hell - die Kachel wie entworfen, mit eigenem Grund.
* dunkel - ohne Grund. iOS legt seinen eigenen dunklen Verlauf darunter; ein
* mitgeliefertes Schwarz wuerde darauf als Kasten sichtbar bleiben.
* getoent - ohne Grund und ohne Farbe. iOS faerbt das Bild selbst nach der
* Wahl des Nutzers ein und wertet dafuer die Helligkeit aus - das
* Rot der 360 wird deshalb zu einem helleren Grau als der Rest,
* damit die Zahl auch getoent noch abgesetzt bleibt.
*
* MASSE
* -----
* Alles als Anteil der Kantenlaenge, hergeleitet aus dem freigegebenen
* Entwurf (Flex-Spalte, Abstand 0,02 - siehe index.html):
*
* Wort 0,095 | Abstand 0,02 | Fahrzeug 0,54 | Abstand 0,02 | Zahl 0,17
* zusammen 0,845, der Rest verteilt sich gleichmaessig oben und unten.
*/
const fs = require("fs")
const path = require("path")
const SCHRIFTEN = path.join(__dirname, "..", "src", "assets", "audi", "schriften")
/* Das CI-Fahrzeug kommt aus dem Panel selbst - eine zweite Kopie des Pfades
waere eine zweite Quelle fuer dieselbe Form. */
const PANEL = path.join(
__dirname,
"..",
"..",
"custom_components",
"audi_dashboard",
"frontend",
"audi-dashboard-app.js",
)
const MARKE = "audi: '<path"
const roh = fs.readFileSync(PANEL, "utf8")
const von = roh.indexOf(MARKE)
if (von < 0) throw new Error("ICONS.audi nicht in audi-dashboard-app.js gefunden")
const dVon = roh.indexOf('d="', von) + 3
const dBis = roh.indexOf('"', dVon)
const AUTO = roh.slice(dVon, dBis)
if (!AUTO.startsWith("M")) throw new Error("Pfad sieht nicht wie erwartet aus: " + AUTO.slice(0, 30))
function schriftDaten(datei) {
return fs.readFileSync(path.join(SCHRIFTEN, datei)).toString("base64")
}
const TYPE = schriftDaten("audi-type-400.woff2")
const WIDE = schriftDaten("audi-type-wide-300.woff2")
/* Anteile der Kantenlaenge. */
const A = {
wort: 0.095,
fahrzeug: 0.54,
zahl: 0.17,
abstand: 0.02,
}
const S = 1024
const gesamt = (A.wort + A.abstand + A.fahrzeug + A.abstand + A.zahl) * S
const oben = (S - gesamt) / 2
const wortMitte = oben + (A.wort * S) / 2
const autoOben = oben + (A.wort + A.abstand) * S
const autoKante = A.fahrzeug * S
const zahlMitte = autoOben + autoKante + A.abstand * S + (A.zahl * S) / 2
/** Das CI-Fahrzeug aus dem 24er-Raster auf seine Kachelgroesse gebracht. */
function fahrzeug(farbe) {
const faktor = autoKante / 24
const links = (S - autoKante) / 2
return `<g transform="translate(${links.toFixed(2)} ${autoOben.toFixed(2)}) scale(${faktor.toFixed(5)})"><path d="${AUTO}" fill="${farbe}"/></g>`
}
/**
* @param {object} o
* @param {string|null} o.grund Hintergrund, oder null fuer keinen
* @param {string} o.vorn Wort und Fahrzeug
* @param {string} o.akzent die 360
*/
function symbol({ grund, vorn, akzent }) {
return `<svg xmlns="http://www.w3.org/2000/svg" width="${S}" height="${S}" viewBox="0 0 ${S} ${S}">
<style>
@font-face { font-family: "Audi Type"; font-weight: 400; src: url(data:font/woff2;base64,${TYPE}) format("woff2"); }
@font-face { font-family: "Audi Type Wide"; font-weight: 300; src: url(data:font/woff2;base64,${WIDE}) format("woff2"); }
.wort { font-family: "Audi Type"; font-weight: 400; letter-spacing: -0.01em; }
.zahl { font-family: "Audi Type Wide"; font-weight: 300; letter-spacing: -0.03em; }
</style>
${grund ? ` <rect width="${S}" height="${S}" fill="${grund}"/>\n` : ""}\
<text class="wort" x="${S / 2}" y="${wortMitte.toFixed(2)}" font-size="${(A.wort * S).toFixed(2)}" fill="${vorn}" text-anchor="middle" dominant-baseline="central">DataMetric</text>
${fahrzeug(vorn)}
<text class="zahl" x="${S / 2}" y="${zahlMitte.toFixed(2)}" font-size="${(A.zahl * S).toFixed(2)}" fill="${akzent}" text-anchor="middle" dominant-baseline="central">360</text>
</svg>
`
}
const AUSFUEHRUNGEN = {
/* Nacht-Canvas und Audi-Rot aus den Tokens des Projekts. */
hell: { grund: "#0C1014", vorn: "#FFFFFF", akzent: "#F50537" },
dunkel: { grund: null, vorn: "#FFFFFF", akzent: "#F50537" },
/* Getoent wertet iOS die Helligkeit aus: Weiss fuer Wort und Fahrzeug, ein
helles Grau fuer die Zahl - so bleibt sie abgesetzt, ohne eine Farbe zu
behaupten, die es getoent nicht gibt. */
getoent: { grund: null, vorn: "#FFFFFF", akzent: "#B4B4B8" },
}
const ZIEL = path.join(__dirname, "..", "native", "logo")
fs.mkdirSync(ZIEL, { recursive: true })
for (const [name, o] of Object.entries(AUSFUEHRUNGEN)) {
const datei = path.join(ZIEL, `AppIcon-${name}.svg`)
fs.writeFileSync(datei, symbol(o), "utf8")
console.log(`${path.basename(datei)} ${(fs.statSync(datei).size / 1024).toFixed(0)} KB`)
}
console.log("")
console.log("Masse bei 1024:")
console.log(` Wort Mitte y=${wortMitte.toFixed(1)} Groesse ${(A.wort * S).toFixed(1)}`)
console.log(` Fahrzeug oben y=${autoOben.toFixed(1)} Kante ${autoKante.toFixed(1)}`)
console.log(` Zahl Mitte y=${zahlMitte.toFixed(1)} Groesse ${(A.zahl * S).toFixed(1)}`)