mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
Improve watermark rendering with centered rotation and per-character transformations
- Enhanced text watermark rendering to calculate accurate dimensions for center-point rotation. - Added precise positioning and rotation for individual characters in per-letter variations. - Updated baseline transformations to ensure proper alignment and spacing of characters and lines.
This commit is contained in:
parent
22df750009
commit
b49aa1e849
@ -508,9 +508,47 @@ public class WatermarkController {
|
|||||||
// Standard rendering without per-letter variations
|
// Standard rendering without per-letter variations
|
||||||
contentStream.setFont(wmFont, wmFontSize);
|
contentStream.setFont(wmFont, wmFontSize);
|
||||||
contentStream.setNonStrokingColor(wmColor);
|
contentStream.setNonStrokingColor(wmColor);
|
||||||
|
|
||||||
|
// Calculate actual watermark dimensions for center-point rotation
|
||||||
|
float actualMaxLineWidth = 0;
|
||||||
|
for (String textLine : textLines) {
|
||||||
|
float lineWidth = wmFont.getStringWidth(textLine) * wmFontSize / 1000;
|
||||||
|
if (lineWidth > actualMaxLineWidth) {
|
||||||
|
actualMaxLineWidth = lineWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float actualWatermarkWidth = actualMaxLineWidth;
|
||||||
|
float actualWatermarkHeight = wmFontSize * textLines.length;
|
||||||
|
|
||||||
|
// Calculate center point of the watermark
|
||||||
|
float centerX = x + actualWatermarkWidth / 2;
|
||||||
|
float centerY = y + actualWatermarkHeight / 2;
|
||||||
|
|
||||||
|
// Apply rotation around center point
|
||||||
|
// To rotate around center, we need to:
|
||||||
|
// 1. Calculate offset from center to bottom-left corner
|
||||||
|
// 2. Rotate that offset
|
||||||
|
// 3. Add rotated offset to center to get final position
|
||||||
|
double rotationRad = Math.toRadians(wmRotation);
|
||||||
|
double cos = Math.cos(rotationRad);
|
||||||
|
double sin = Math.sin(rotationRad);
|
||||||
|
|
||||||
|
// Offset from center to bottom-left corner (where text starts)
|
||||||
|
float offsetX = -actualWatermarkWidth / 2;
|
||||||
|
float offsetY = -actualWatermarkHeight / 2;
|
||||||
|
|
||||||
|
// Apply rotation to the offset
|
||||||
|
float rotatedOffsetX = (float) (offsetX * cos - offsetY * sin);
|
||||||
|
float rotatedOffsetY = (float) (offsetX * sin + offsetY * cos);
|
||||||
|
|
||||||
|
// Final position where text should start
|
||||||
|
float finalX = centerX + rotatedOffsetX;
|
||||||
|
float finalY = centerY + rotatedOffsetY;
|
||||||
|
|
||||||
contentStream.beginText();
|
contentStream.beginText();
|
||||||
contentStream.setTextMatrix(
|
contentStream.setTextMatrix(
|
||||||
Matrix.getRotateInstance((float) Math.toRadians(wmRotation), x, y));
|
Matrix.getRotateInstance(
|
||||||
|
(float) Math.toRadians(wmRotation), finalX, finalY));
|
||||||
|
|
||||||
for (String textLine : textLines) {
|
for (String textLine : textLines) {
|
||||||
contentStream.showText(textLine);
|
contentStream.showText(textLine);
|
||||||
@ -544,11 +582,16 @@ public class WatermarkController {
|
|||||||
WatermarkRandomizer randomizer)
|
WatermarkRandomizer randomizer)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
float currentX = startX;
|
// Convert base rotation to radians for trigonometric calculations
|
||||||
float currentY = startY;
|
double baseRotationRad = Math.toRadians(baseRotation);
|
||||||
|
double cosBase = Math.cos(baseRotationRad);
|
||||||
|
double sinBase = Math.sin(baseRotationRad);
|
||||||
|
|
||||||
|
float currentLineOffset = 0; // Vertical offset for each line
|
||||||
|
|
||||||
for (String line : textLines) {
|
for (String line : textLines) {
|
||||||
currentX = startX;
|
float currentCharOffset = 0; // Horizontal offset along the baseline for current line
|
||||||
|
|
||||||
for (int i = 0; i < line.length(); i++) {
|
for (int i = 0; i < line.length(); i++) {
|
||||||
char c = line.charAt(i);
|
char c = line.charAt(i);
|
||||||
String charStr = String.valueOf(c);
|
String charStr = String.valueOf(c);
|
||||||
@ -564,11 +607,13 @@ public class WatermarkController {
|
|||||||
? randomizer.generateRandomColorFromPalette(perLetterColorCount)
|
? randomizer.generateRandomColorFromPalette(perLetterColorCount)
|
||||||
: baseColor;
|
: baseColor;
|
||||||
|
|
||||||
float letterRotation =
|
// Calculate per-letter rotation: base rotation + additional per-letter variation
|
||||||
|
float additionalRotation =
|
||||||
perLetterOrientation
|
perLetterOrientation
|
||||||
? randomizer.generatePerLetterRotationInRange(
|
? randomizer.generatePerLetterRotationInRange(
|
||||||
perLetterOrientationMin, perLetterOrientationMax)
|
perLetterOrientationMin, perLetterOrientationMax)
|
||||||
: baseRotation;
|
: 0f;
|
||||||
|
float letterRotation = baseRotation + additionalRotation;
|
||||||
|
|
||||||
// Determine per-letter font
|
// Determine per-letter font
|
||||||
PDFont letterFont = baseFont;
|
PDFont letterFont = baseFont;
|
||||||
@ -584,23 +629,60 @@ public class WatermarkController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate letter dimensions for center-point rotation
|
||||||
|
float charWidth = letterFont.getStringWidth(charStr) * letterSize / 1000;
|
||||||
|
float charHeight = letterSize; // Approximate height as font size
|
||||||
|
|
||||||
|
// Calculate the position of this letter along the rotated baseline
|
||||||
|
// Transform from local coordinates (along baseline) to page coordinates
|
||||||
|
float localX = currentCharOffset;
|
||||||
|
float localY = -currentLineOffset; // Negative because text lines go downward
|
||||||
|
|
||||||
|
// Apply rotation transformation to position the letter on the rotated baseline
|
||||||
|
float transformedX = (float) (startX + localX * cosBase - localY * sinBase);
|
||||||
|
float transformedY = (float) (startY + localX * sinBase + localY * cosBase);
|
||||||
|
|
||||||
|
// Calculate letter's center point on the rotated baseline
|
||||||
|
float letterCenterX = transformedX + charWidth / 2;
|
||||||
|
float letterCenterY = transformedY + charHeight / 2;
|
||||||
|
|
||||||
|
// Apply rotation around letter center
|
||||||
|
// Calculate offset from center to bottom-left corner
|
||||||
|
double letterRotationRad = Math.toRadians(letterRotation);
|
||||||
|
double cosLetter = Math.cos(letterRotationRad);
|
||||||
|
double sinLetter = Math.sin(letterRotationRad);
|
||||||
|
|
||||||
|
float offsetX = -charWidth / 2;
|
||||||
|
float offsetY = -charHeight / 2;
|
||||||
|
|
||||||
|
// Rotate the offset
|
||||||
|
float rotatedOffsetX = (float) (offsetX * cosLetter - offsetY * sinLetter);
|
||||||
|
float rotatedOffsetY = (float) (offsetX * sinLetter + offsetY * cosLetter);
|
||||||
|
|
||||||
|
// Final position where letter should be rendered
|
||||||
|
float finalLetterX = letterCenterX + rotatedOffsetX;
|
||||||
|
float finalLetterY = letterCenterY + rotatedOffsetY;
|
||||||
|
|
||||||
// Set font and color
|
// Set font and color
|
||||||
contentStream.setFont(letterFont, letterSize);
|
contentStream.setFont(letterFont, letterSize);
|
||||||
contentStream.setNonStrokingColor(letterColor);
|
contentStream.setNonStrokingColor(letterColor);
|
||||||
|
|
||||||
// Render the character
|
// Render the character at the transformed position with combined rotation
|
||||||
contentStream.beginText();
|
contentStream.beginText();
|
||||||
contentStream.setTextMatrix(
|
contentStream.setTextMatrix(
|
||||||
Matrix.getRotateInstance(
|
Matrix.getRotateInstance(
|
||||||
(float) Math.toRadians(letterRotation), currentX, currentY));
|
(float) Math.toRadians(letterRotation),
|
||||||
|
finalLetterX,
|
||||||
|
finalLetterY));
|
||||||
contentStream.showText(charStr);
|
contentStream.showText(charStr);
|
||||||
contentStream.endText();
|
contentStream.endText();
|
||||||
|
|
||||||
// Advance position
|
// Advance position along the baseline for the next character
|
||||||
float charWidth = letterFont.getStringWidth(charStr) * letterSize / 1000;
|
currentCharOffset += charWidth;
|
||||||
currentX += charWidth;
|
|
||||||
}
|
}
|
||||||
currentY -= baseFontSize;
|
|
||||||
|
// Move to next line (advance vertically in local coordinates)
|
||||||
|
currentLineOffset += baseFontSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user