15 gebündelte Open-Source-Schriften statt Systemfonts
Text-Werkzeug nutzte bisher OS-abhängige Systemfonts (Helvetica/Arial/ Times/Georgia/Courier) — Darstellung und PDF-Export waren damit nicht plattformunabhängig deterministisch. Jetzt 15 kuratierte SIL-OFL- Schriften lokal als WOFF2 gebündelt (je mit OFL.txt-Lizenz): Inter, Work Sans, IBM Plex Sans/Mono, Source Sans 3, Space Grotesk, Manrope, Outfit, DM Sans, Public Sans, Karla, Rubik, Jost, Archivo, Source Serif 4. Ein späterer Einstellungen-Dialog kann weitere Schriften nachladen.
This commit is contained in:
@@ -5,6 +5,7 @@ import { ErrorBoundary } from "./ui/ErrorBoundary";
|
||||
import { getLanguage, setLanguage } from "./i18n";
|
||||
import type { Language } from "./i18n";
|
||||
import "./styles.css";
|
||||
import "./text/fonts.css";
|
||||
|
||||
// Sprach-Naht für Werkzeuge/Tests (und einen späteren Umschalter): die i18n-
|
||||
// Steuerung am window verfügbar machen. Identifier englisch; Werte übersetzbar.
|
||||
|
||||
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Lokal gebuendelte Open-Source-Schriften (SIL Open Font License) fuer das
|
||||
* Text-Werkzeug (Raumstempel/Text-Objekte). Damit ist die Schriftdarstellung
|
||||
* unabhaengig vom Betriebssystem und der PDF-Export deterministisch.
|
||||
*
|
||||
* Jede Schrift bringt ihre OFL.txt unter public/fonts/<slug>/OFL.txt mit.
|
||||
* Herkunft: Google Fonts (css2-API), WOFF2, Subset "latin".
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/inter/inter-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/inter/inter-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/inter/inter-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/inter/inter-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Work Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/work-sans/work-sans-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Work Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/work-sans/work-sans-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Work Sans";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/work-sans/work-sans-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Work Sans";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/work-sans/work-sans-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "IBM Plex Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/ibm-plex-sans/ibm-plex-sans-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "IBM Plex Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/ibm-plex-sans/ibm-plex-sans-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "IBM Plex Sans";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/ibm-plex-sans/ibm-plex-sans-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "IBM Plex Sans";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/ibm-plex-sans/ibm-plex-sans-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "IBM Plex Mono";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/ibm-plex-mono/ibm-plex-mono-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "IBM Plex Mono";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/ibm-plex-mono/ibm-plex-mono-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "IBM Plex Mono";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/ibm-plex-mono/ibm-plex-mono-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "IBM Plex Mono";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/ibm-plex-mono/ibm-plex-mono-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Sans 3";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/source-sans-3/source-sans-3-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Sans 3";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/source-sans-3/source-sans-3-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Sans 3";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/source-sans-3/source-sans-3-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Sans 3";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/source-sans-3/source-sans-3-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Space Grotesk";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/space-grotesk/space-grotesk-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Space Grotesk";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/space-grotesk/space-grotesk-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Manrope";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/manrope/manrope-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Manrope";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/manrope/manrope-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Outfit";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/outfit/outfit-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Outfit";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/outfit/outfit-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "DM Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/dm-sans/dm-sans-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "DM Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/dm-sans/dm-sans-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "DM Sans";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/dm-sans/dm-sans-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "DM Sans";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/dm-sans/dm-sans-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Public Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/public-sans/public-sans-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Public Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/public-sans/public-sans-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Public Sans";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/public-sans/public-sans-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Public Sans";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/public-sans/public-sans-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Karla";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/karla/karla-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Karla";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/karla/karla-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Karla";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/karla/karla-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Karla";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/karla/karla-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Rubik";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/rubik/rubik-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Rubik";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/rubik/rubik-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Rubik";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/rubik/rubik-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Rubik";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/rubik/rubik-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Jost";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/jost/jost-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Jost";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/jost/jost-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Jost";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/jost/jost-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Jost";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/jost/jost-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Archivo";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/archivo/archivo-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Archivo";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/archivo/archivo-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Archivo";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/archivo/archivo-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Archivo";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/archivo/archivo-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Serif 4";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/source-serif-4/source-serif-4-400-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Serif 4";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/source-serif-4/source-serif-4-700-normal.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Serif 4";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("/fonts/source-serif-4/source-serif-4-400-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Serif 4";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("/fonts/source-serif-4/source-serif-4-700-italic.woff2") format("woff2");
|
||||
}
|
||||
|
||||
+23
-7
@@ -519,14 +519,30 @@ function Segment({
|
||||
);
|
||||
}
|
||||
|
||||
/** Systemfont-Auswahl der Text-Gruppe. */
|
||||
/**
|
||||
* Schriftauswahl der Text-Gruppe: 15 kuratierte, lokal gebuendelte
|
||||
* Open-Source-Schriften (SIL Open Font License, siehe `src/text/fonts.css`
|
||||
* und `public/fonts/<slug>/OFL.txt`). Bewusst KEINE Systemfonts mehr — die
|
||||
* Darstellung soll unabhaengig vom Betriebssystem und der PDF-Export
|
||||
* deterministisch sein. Ein spaeterer Einstellungen-Dialog kann weitere
|
||||
* Schriften nachladen; das hier ist die Standardliste.
|
||||
*/
|
||||
const TEXT_FONTS: string[] = [
|
||||
"Helvetica",
|
||||
"Arial",
|
||||
"Inter",
|
||||
"Times New Roman",
|
||||
"Georgia",
|
||||
"Courier New",
|
||||
"Work Sans",
|
||||
"IBM Plex Sans",
|
||||
"IBM Plex Mono",
|
||||
"Source Sans 3",
|
||||
"Space Grotesk",
|
||||
"Manrope",
|
||||
"Outfit",
|
||||
"DM Sans",
|
||||
"Public Sans",
|
||||
"Karla",
|
||||
"Rubik",
|
||||
"Jost",
|
||||
"Archivo",
|
||||
"Source Serif 4",
|
||||
];
|
||||
|
||||
/** Grössen-Presets (pt) der Text-Gruppe. */
|
||||
@@ -547,7 +563,7 @@ function TextGroup({
|
||||
}) {
|
||||
// Defaults für neuen Text, solange nichts Text-artiges selektiert ist. Bei
|
||||
// aktivem Ziel spiegeln die Controls die gemeinsamen Werte des Ziels wider.
|
||||
const [defFont, setDefFont] = useState<string>("Helvetica");
|
||||
const [defFont, setDefFont] = useState<string>("Inter");
|
||||
const [defSize, setDefSize] = useState<number>(12);
|
||||
const [defAlign, setDefAlign] = useState<Align>("left");
|
||||
const [defBold, setDefBold] = useState(false);
|
||||
|
||||
Reference in New Issue
Block a user