@@ -502,9 +502,25 @@ function generatePostcardSVG(text, format, options = {}) {
return out ;
}
// Text links (L-förmig). Nur DER Text kann „zu lang" sein (Nutzer kürzt ihn) .
// Etwas Abstand nach dem Absender (Absender endet bei y≈12 mm ).
const baseline0 = mmToPx ( 18 ) + fontSizePx ;
// Absender oben links – ZUERST, damit der Text knapp darunter beginnen kann .
// Größe folgt der „Absender-Größe" aus dem manuellen Druck (options.senderScale ).
let senderBottomPx = mmToPx ( 2 ) ;
if ( sender ) {
const senderScale = Math . max ( 0.5 , Math . min ( 1.8 , Number ( options . senderScale ) || 1 ) ) ;
const senderSize = FONT _SIZE _PX * 0.55 * senderScale ;
const senderLH = ( baseLineHeightPx / FONT _SIZE _PX ) * senderSize ;
const senderLines = wrapTextToLinesByWidth ( { text : sender , maxWidthPx : mmToPx ( textUpperRightMm - textLeftMm ) , fontFileName : fontFile , fontSizePx : senderSize } ) . slice ( 0 , 2 ) ;
const senderStartY = mmToPx ( 2 ) + senderSize ;
paths . push ( ... layoutTextToPaths ( {
lines : senderLines , fontFileName : fontFile , fontSizePx : senderSize ,
startX : mmToPx ( textLeftMm ) , startY : senderStartY , lineHeightPx : senderLH , realisticHandwriting : realistic ,
} ) ) ;
senderBottomPx = senderStartY + Math . max ( 0 , senderLines . length - 1 ) * senderLH + senderSize * 0.3 ;
}
// Text links (L-förmig). Beginn nur ETWAS unter dem Absender (≈2 mm); ohne
// Absender wie im Maßblatt bei y≈14 mm. Nur DER Text kann „zu lang" sein.
const baseline0 = ( sender ? senderBottomPx + mmToPx ( 2 ) : mmToPx ( 14 ) ) + fontSizePx ;
bodyLineLimit = Math . max ( 1 , Math . floor ( ( mmToPx ( maxYmm ) - baseline0 ) / lineHeightPx ) + 1 ) ;
if ( body ) {
const bodyLines = flowVariabel ( body , fontSizePx , baseline0 , lineHeightPx ) ;
@@ -516,30 +532,22 @@ function generatePostcardSVG(text, format, options = {}) {
} ) ) ;
}
// Absender oben links (2 Zeilen), klein genug für die 10-mm-Zone.
if ( sender ) {
const senderSize = FONT _SIZE _PX * 0.55 * Math . max ( 0.7 , Math . min ( 1.2 , Number ( options . senderScale ) || 1 ) ) ;
const senderLH = ( baseLineHeightPx / FONT _SIZE _PX ) * senderSize ;
const senderLines = wrapTextToLinesByWidth ( { text : sender , maxWidthPx : mmToPx ( textUpperRightMm - textLeftMm ) , fontFileName : fontFile , fontSizePx : senderSize } ) . slice ( 0 , 2 ) ;
paths . push ( ... layoutTextToPaths ( {
lines : senderLines , fontFileName : fontFile , fontSizePx : senderSize ,
startX : mmToPx ( textLeftMm ) , startY : mmToPx ( 2 ) + senderSize , lineHeightPx : senderLH , realisticHandwriting : realistic ,
} ) ) ;
}
// Empfänger im sicheren Adressfeld (rechts unten). Passt der Block nicht in die
// 46 mm hohe Zone, wird die Schrift automatisch verkleinert – so bleibt die
// Codierzone (unten) IMMER frei und es gibt keinen „Adresse zu lang"-Fehler.
// Empfänger im sicheren Adressfeld (rechts unten). Größe folgt der „Schriftgröße
// Kuvert" (options.recipientScale). Passt der Block nicht in die 46-mm-Zone, wird
// er automatisch verkleinert – so bleibt die Codierzone IMMER frei.
if ( recipient ) {
const feldOben = mmToPx ( addrTopMm ) ;
const feldUnten = mmToPx ( maxYmm ) ;
const feldBreite = mmToPx ( addrRightMm - addrLeftMm ) ;
le t recSiz e = fontSizePx ;
le t recLH = lineHeightPx ;
cons t recScal e = Math . max ( 0.6 , Math . min ( 1.6 , Number ( options . recipientScale ) || 1 ) ) ;
cons t recBaseSize = FONT _SIZE _PX * recScale ;
const recBaseLH = baseLineHeightPx * recScale ;
let recSize = recBaseSize ;
let recLH = recBaseLH ;
let recLines = [ ] ;
for ( const scale of [ 1 , 0.9 , 0.8 , 0.72 , 0.65 , 0.6 ] ) {
recSize = font SizePx * scale ;
recLH = lineHeightPx * scale ;
recSize = recBase Size * scale ;
recLH = recBaseLH * scale ;
recLines = wrapTextToLinesByWidth ( { text : recipient , maxWidthPx : feldBreite , fontFileName : fontFile , fontSizePx : recSize } ) ;
const blockUnten = feldOben + recSize + Math . max ( 0 , recLines . length - 1 ) * recLH + recSize * 0.3 ;
if ( blockUnten <= feldUnten ) break ;