watermark fix
This commit is contained in:
@@ -62,10 +62,6 @@ dependencies {
|
|||||||
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||||
implementation 'io.micrometer:micrometer-core'
|
implementation 'io.micrometer:micrometer-core'
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/com.cybozu.labs/langdetect
|
|
||||||
implementation group: 'com.cybozu.labs', name: 'langdetect', version: '1.1-20120112'
|
|
||||||
|
|
||||||
|
|
||||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+44
-34
@@ -5,6 +5,8 @@ import java.io.File;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@@ -23,14 +25,11 @@ import org.springframework.web.bind.annotation.RequestPart;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import com.cybozu.labs.langdetect.Detector;
|
|
||||||
import com.cybozu.labs.langdetect.DetectorFactory;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
@RestController
|
@RestController
|
||||||
@Tag(name = "Security", description = "Security APIs")
|
@Tag(name = "Security", description = "Security APIs")
|
||||||
public class WatermarkController {
|
public class WatermarkController {
|
||||||
@@ -42,6 +41,12 @@ public class WatermarkController {
|
|||||||
@RequestPart(required = true, value = "fileInput")
|
@RequestPart(required = true, value = "fileInput")
|
||||||
@Parameter(description = "The input PDF file to add a watermark")
|
@Parameter(description = "The input PDF file to add a watermark")
|
||||||
MultipartFile pdfFile,
|
MultipartFile pdfFile,
|
||||||
|
@RequestParam(defaultValue = "roman", name = "alphabet")
|
||||||
|
@Parameter(description = "The selected alphabet",
|
||||||
|
schema = @Schema(type = "string",
|
||||||
|
allowableValues = {"roman","arabic","japanese","korean","chinese"},
|
||||||
|
defaultValue = "roman"))
|
||||||
|
String alphabet,
|
||||||
@RequestParam("watermarkText")
|
@RequestParam("watermarkText")
|
||||||
@Parameter(description = "The watermark text to add to the PDF file")
|
@Parameter(description = "The watermark text to add to the PDF file")
|
||||||
String watermarkText,
|
String watermarkText,
|
||||||
@@ -63,7 +68,7 @@ public class WatermarkController {
|
|||||||
|
|
||||||
// Load the input PDF
|
// Load the input PDF
|
||||||
PDDocument document = PDDocument.load(pdfFile.getInputStream());
|
PDDocument document = PDDocument.load(pdfFile.getInputStream());
|
||||||
|
String producer = document.getDocumentInformation().getProducer();
|
||||||
// Create a page in the document
|
// Create a page in the document
|
||||||
for (PDPage page : document.getPages()) {
|
for (PDPage page : document.getPages()) {
|
||||||
|
|
||||||
@@ -75,42 +80,39 @@ public class WatermarkController {
|
|||||||
graphicsState.setNonStrokingAlphaConstant(opacity);
|
graphicsState.setNonStrokingAlphaConstant(opacity);
|
||||||
contentStream.setGraphicsStateParameters(graphicsState);
|
contentStream.setGraphicsStateParameters(graphicsState);
|
||||||
|
|
||||||
DetectorFactory.loadProfile("profiles");
|
|
||||||
|
|
||||||
Detector detector = DetectorFactory.create();
|
String resourceDir = "";
|
||||||
detector.append(watermarkText);
|
PDFont font = PDType1Font.HELVETICA_BOLD;
|
||||||
String lang = detector.detect();
|
switch (alphabet) {
|
||||||
|
case "arabic":
|
||||||
|
resourceDir = "static/fonts/NotoSansArabic-Regular.ttf";
|
||||||
|
break;
|
||||||
|
case "japanese":
|
||||||
|
resourceDir = "static/fonts/Meiryo.ttf";
|
||||||
|
break;
|
||||||
|
case "korean":
|
||||||
|
resourceDir = "static/fonts/malgun.ttf";
|
||||||
|
break;
|
||||||
|
case "chinese":
|
||||||
|
resourceDir = "static/fonts/SimSun.ttf";
|
||||||
|
break;
|
||||||
|
case "roman":
|
||||||
|
default:
|
||||||
|
resourceDir = "static/fonts/NotoSans-Regular.ttf";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
System.out.println("Detected lang" + lang);
|
|
||||||
// Set font of watermark
|
|
||||||
// Load NotoSans-Regular font from resources
|
|
||||||
String resourceDir = "";
|
|
||||||
PDFont font = PDType1Font.HELVETICA_BOLD;
|
|
||||||
switch (lang) {
|
|
||||||
case "ar":
|
|
||||||
resourceDir = "src/main/resources/static/fonts/NotoSansArabic-Regular.ttf";
|
|
||||||
break;
|
|
||||||
case "ja":
|
|
||||||
resourceDir = "src/main/resources/static/fonts/NotoSansJP-Regular.otf";
|
|
||||||
break;
|
|
||||||
case "ko":
|
|
||||||
resourceDir = "src/main/resources/static/fonts/NotoSansKR-Regular.otf";
|
|
||||||
break;
|
|
||||||
case "zh-cn":
|
|
||||||
resourceDir = "src/main/resources/static/fonts/NotoSansSC-Regular.otf";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
font = PDType1Font.HELVETICA_BOLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!resourceDir.equals("")) {
|
if(!resourceDir.equals("")) {
|
||||||
ClassPathResource classPathResource = new ClassPathResource("static/fonts/NotoSans-Regular.ttf");
|
ClassPathResource classPathResource = new ClassPathResource(resourceDir);
|
||||||
File tempFile = File.createTempFile("NotoSans-Regular", ".ttf");
|
String fileExtension = resourceDir.substring(resourceDir.lastIndexOf("."));
|
||||||
|
File tempFile = File.createTempFile("NotoSansFont", fileExtension);
|
||||||
try (InputStream is = classPathResource.getInputStream(); FileOutputStream os = new FileOutputStream(tempFile)) {
|
try (InputStream is = classPathResource.getInputStream(); FileOutputStream os = new FileOutputStream(tempFile)) {
|
||||||
IOUtils.copy(is, os);
|
IOUtils.copy(is, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
font = PDType0Font.load(document, tempFile);
|
font = PDType0Font.load(document, tempFile);
|
||||||
|
tempFile.deleteOnExit();
|
||||||
}
|
}
|
||||||
contentStream.beginText();
|
contentStream.beginText();
|
||||||
contentStream.setFont(font, fontSize);
|
contentStream.setFont(font, fontSize);
|
||||||
@@ -127,11 +129,19 @@ public class WatermarkController {
|
|||||||
// Add the watermark text
|
// Add the watermark text
|
||||||
for (int i = 0; i < watermarkRows; i++) {
|
for (int i = 0; i < watermarkRows; i++) {
|
||||||
for (int j = 0; j < watermarkCols; j++) {
|
for (int j = 0; j < watermarkCols; j++) {
|
||||||
contentStream.setTextMatrix(Matrix.getRotateInstance((float) Math.toRadians(rotation), j * watermarkWidth, i * watermarkHeight));
|
|
||||||
|
if(producer.contains("Google Docs")) {
|
||||||
|
//This fixes weird unknown google docs y axis rotation/flip issue
|
||||||
|
//TODO: Long term fix one day
|
||||||
|
//contentStream.setTextMatrix(1, 0, 0, -1, j * watermarkWidth, pageHeight - i * watermarkHeight);
|
||||||
|
Matrix matrix = new Matrix(1, 0, 0, -1, j * watermarkWidth, pageHeight - i * watermarkHeight);
|
||||||
|
contentStream.setTextMatrix(matrix);
|
||||||
|
} else {
|
||||||
|
contentStream.setTextMatrix(Matrix.getRotateInstance((float) Math.toRadians(rotation), j * watermarkWidth, i * watermarkHeight));
|
||||||
|
}
|
||||||
contentStream.showTextWithPositioning(new Object[] { watermarkText });
|
contentStream.showTextWithPositioning(new Object[] { watermarkText });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentStream.endText();
|
contentStream.endText();
|
||||||
|
|
||||||
// Close the content stream
|
// Close the content stream
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -18,6 +18,17 @@
|
|||||||
<label th:text="#{watermark.selectText.1}"></label>
|
<label th:text="#{watermark.selectText.1}"></label>
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="fontSize" th:text="#{alphabet}"></label>
|
||||||
|
<select class="form-control" name="alphabet" id="alphabet-select">
|
||||||
|
<option value="romain">Roman</option>
|
||||||
|
<option value="arabic">العربية</option>
|
||||||
|
<option value="japanese">日本語</option>
|
||||||
|
<option value="korean">한국어</option>
|
||||||
|
<option value="chinese">简体中文</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="watermarkText" th:text="#{watermark.selectText.2}"></label>
|
<label for="watermarkText" th:text="#{watermark.selectText.2}"></label>
|
||||||
<input type="text" id="watermarkText" name="watermarkText" class="form-control" placeholder="Stirling-PDF" required />
|
<input type="text" id="watermarkText" name="watermarkText" class="form-control" placeholder="Stirling-PDF" required />
|
||||||
|
|||||||
Reference in New Issue
Block a user