Dokument skalowania Java iText do formatu A4
Mam następującą metodę, która „zmienia rozmiar” wszystkich stron dokumentu do rozmiaru strony A4:
for (PdfDocument doc : pdfDocuments) {
int n = doc.getNumberOfPages();
for (int i = 1; i <= n; i++) {
PdfPage page = doc.getPage(i);
Rectangle media = page.getCropBox();
if (media == null) {
media = page.getMediaBox();
}
Rectangle crop = new Rectangle(0, 0, 210, 297);
page.setMediaBox(crop);
page.setCropBox(crop);
// The content, placed on a content stream before, will be rendered before the other content
// and, therefore, could be understood as a background (bottom "layer")
new PdfCanvas(page.newContentStreamBefore(),
page.getResources(), doc).writeLiteral("\nq 0.5 0 0 0.5 0 0 cm\nq\n");
// The content, placed on a content stream after, will be rendered after the other content
// and, therefore, could be understood as a foreground (top "layer")
new PdfCanvas(page.newContentStreamAfter(),
page.getResources(), doc).writeLiteral("\nQ\nQ\n");
}
}
Jednak to nie działa zgodnie z oczekiwaniami, strony są przekształcane do formatu A4 (297x210), ALE treść nie jest dopasowywana wewnątrz (skalowana), treść wygląda na obciętą, ponieważ oryginalne strony są większe niż 297X210. Jak mogę to naprawić?
Odpowiedzi
W komentarzu wyjaśniłeś
Chcę, aby obwiednia poprzedniej zawartości została przeskalowana, a do celu dodano margines
Dlatego najpierw musimy określić obwiednię oryginalnej zawartości strony. Można to zrobić za pomocą MarginFinderklasy z tej odpowiedzi . Uwaga: ta klasa określa obwiednię całej treści, nawet jeśli jest to tylko biały prostokąt wizualnie nie różniący się od żadnej treści lub coś, co wcześniej znajdowało się poza polem przycinania ... Jeśli Twój przypadek użycia tego wymaga, być może będziesz musiał rozszerzyć tę klasę wziąć pod uwagę również takie okoliczności.
Dzięki ramce ograniczającej zawartość ustalono, że pozostaje tylko trochę obliczeń.
Poniższa metoda określa ramkę ograniczającą przy użyciu powyższej klasy, odpowiednio przekształca zawartość i zmienia pole kadrowania wyniku.
void scale(PdfDocument pdfDocument, Rectangle pageSize, Rectangle pageBodySize) {
int n = pdfDocument.getNumberOfPages();
for (int i = 1; i <= n; i++) {
PdfPage page = pdfDocument.getPage(i);
MarginFinder marginFinder = new MarginFinder();
PdfCanvasProcessor pdfCanvasProcessor = new PdfCanvasProcessor(marginFinder);
pdfCanvasProcessor.processPageContent(page);
Rectangle boundingBox = marginFinder.getBoundingBox();
if (boundingBox == null || boundingBox.getWidth() == 0 || boundingBox.getHeight() == 0) {
System.err.printf("Cannot scale page %d contents with bounding box %s\n", i , boundingBox);
continue;
} else {
// Scale and move content into A4 with margin
double scale = 0, xDiff= 0, yDiff = 0;
double xScale = pageBodySize.getWidth()/boundingBox.getWidth();
double yScale = pageBodySize.getHeight()/boundingBox.getHeight();
if (xScale < yScale) {
yDiff = boundingBox.getHeight() * (yScale / xScale - 1) / 2;
scale = xScale;
} else {
xDiff = boundingBox.getWidth() * (xScale / yScale - 1) / 2;
scale = yScale;
}
AffineTransform transform = AffineTransform.getTranslateInstance(pageBodySize.getLeft() + xDiff, pageBodySize.getBottom() + yDiff);
transform.scale(scale, scale);
transform.translate(-boundingBox.getLeft(), -boundingBox.getBottom());
new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDocument)
.concatMatrix(transform);
}
page.setMediaBox(pageSize);
page.setCropBox(pageSize);
}
}
( Metoda ScaleToA4scale )
W przypadku strony wynikowej w formacie A4 z calem marginesu z każdej strony można to nazwać następująco PdfDocument pdfDocument:
Rectangle pageSize = PageSize.A4;
Rectangle pageBodySize = pageSize.clone().applyMargins(72, 72, 72, 72, false);
scale(pdfDocument, pageSize, pageBodySize);
(fragment testu ScaleToA4testFdaRequiresUseOfEctdFormatAndStandardizedStudyDataInFutureRegulatorySubmissionsSept )