Text Auto-Resize
Der Auto-Resize Mechanismus passt die Schriftgröße automatisch an, damit Text in den Container passt, ohne Wörter zu umbrechen.
Problemstellung
Wenn ein Benutzer Text wie "DEIN FERNSTUDIUM ENTDECKEN" in einen 170px breiten Container eingibt:
- Das Wort "FERNSTUDIUM" ist bei 33px Schriftgröße breiter als der Container
- Ohne Auto-Resize würde das Wort mitten im Wort umbrechen → unschön
Lösung: Zwei-Phasen-Algorithmus
Phase 1: Word-Fit Check
Prüft, ob jedes einzelne Wort in den Container passt:
Input: "DEIN FERNSTUDIUM ENTDECKEN" @ 33px, Container: 170px
Wort-Breiten:
- "DEIN" = 52px ✅
- "FERNSTUDIUM" = 185px ❌ (> 170px)
- "ENTDECKEN" = 128px ✅
Ergebnis: Word-Fit FAILED → Schriftgröße muss reduziert werden
Phase 2: Binary Search für optimale Größe
Findet die größte Schriftgröße, bei der alle Wörter passen:
Binary Search: low=8, high=33
Iteration 1: mid=20 → "FERNSTUDIUM"=112px ✅ → low=20
Iteration 2: mid=26 → "FERNSTUDIUM"=145px ✅ → low=26
Iteration 3: mid=29 → "FERNSTUDIUM"=160px ✅ → low=29
Iteration 4: mid=31 → "FERNSTUDIUM"=172px ❌ → high=31
Iteration 5: mid=30 → "FERNSTUDIUM"=166px ✅ → low=30
Ergebnis: 30px (größte Größe bei der alles passt)
Max-Lines Constraint
Wenn maxLines gesetzt ist, wird zusätzlich geprüft, ob der Text in X Zeilen passt:
Text: "BILDUNG, DIE DICH BEGLEITET"
Container: 170px
maxLines: 2
Bei 33px: 3 Zeilen → zu viele
Bei 25px: 2 Zeilen → passt ✅
Wichtig: Word-Fit wird IMMER zuerst geprüft, auch wenn maxLines gesetzt ist!
Implementierung
Ort: packages/render-engine/ (von Studio und beiden Export-Renderern genutzt)
Text-Messung im Browser über die Canvas API (context.measureText()). Dieselbe
Fit-Logik gilt für Live-Vorschau und Export — es gibt keinen separaten
Export-Messpfad mehr.
Flowchart
┌─────────────────────────────────────┐
│ Auto-Resize Start │
│ (initial_font_size = 33px) │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Phase 1: Check Word-Fit │
│ Passt jedes Wort in Container? │
└──────────────┬──────────────────────┘
│
┌─────┴─────┐
│ │
YES NO
│ │
▼ ▼
┌─────────────┐ ┌─────────────────────────┐
│ Keep Size │ │ Binary Search: │
│ │ │ Find largest size where │
│ │ │ all words fit │
└──────┬──────┘ └───────────┬─────────────┘
│ │
└──────────┬──────────┘
│
▼
┌─────────────────────────────────────┐
│ Phase 2: Check Max-Lines │
│ (nur wenn maxLines gesetzt) │
└──────────────┬──────────────────────┘
│
┌─────┴─────┐
│ │
lines ≤ max lines > max
│ │
▼ ▼
┌─────────────┐ ┌─────────────────────────┐
│ Done │ │ Binary Search: │
│ │ │ Find largest size where │
│ │ │ lines ≤ maxLines │
└─────────────┘ └─────────────────────────┘
Edge Cases
1. Leerer Text
if not text or not text.strip():
return initial_font_size # Keine Änderung
2. Einzelnes sehr langes Wort
Wenn ein Wort selbst bei minimaler Schriftgröße (8px) nicht passt, wird es trotzdem angezeigt (overflow).
3. BBCode Formatierung
BBCode-Tags ([b], [/b]) werden vor der Messung entfernt:
plain_text = re.sub(r'\[[biu]\]|\[\/[biu]\]', '', text)
4. Windows-Zeilenenden
\r\n und \r werden zu \n normalisiert:
text = text.replace('\r\n', '\n').replace('\r', '\n')
Debugging
Bei Problemen mit Auto-Resize:
- Prüfe Container-Breite: Ist sie korrekt gesetzt?
- Prüfe Font-Loading: Wird die richtige Schriftart geladen?
- Vergleiche Browser vs Renderer: Unterschiedliche Schriftgrößen?
- Aktiviere Logging:
print(f"Word '{word}' width: {word_width}px, max: {max_width}px")
Siehe auch
- Layout Engine - Wie Container-Höhen berechnet werden
- Rendering Architecture — gemeinsamer Kern und Export-Ziele