Java iText escala documento para A4
Eu tenho o seguinte método que "redimensiona" todas as páginas de um documento para as dimensões de página 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");
}
}
No entanto, isso não está funcionando como esperado, as páginas estão sendo transformadas em A4 (297x210), MAS o conteúdo não está sendo ajustado (dimensionado), o conteúdo aparece cortado porque as páginas originais são maiores do que 297x210. Como posso consertar isso ?
Respostas
Em um comentário que você esclareceu
Quero que a caixa delimitadora do conteúdo anterior seja dimensionada e uma margem seja adicionada no destino
Portanto, primeiro temos que determinar a caixa delimitadora do conteúdo da página original. Isso pode ser feito usando a MarginFinderclasse desta resposta . Cuidado: essa classe determina a caixa delimitadora de todo o conteúdo, mesmo que seja apenas um retângulo branco visualmente não distinto de nenhum conteúdo ou algo anteriormente fora da caixa de corte ... Se seu caso de uso exigir, você pode ter que estender essa classe levar essas circunstâncias em consideração também.
Com a caixa delimitadora de conteúdo determinada, tudo o que resta fazer é um pouco de cálculo.
O método a seguir determina a caixa delimitadora usando a classe acima, transforma o conteúdo de acordo e altera a caixa de corte resultante.
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);
}
}
( Método ScaleToA4scale )
Para um tamanho de página de resultado A4 com uma polegada de margem em cada lado, você pode chamá-lo assim para PdfDocument pdfDocument:
Rectangle pageSize = PageSize.A4;
Rectangle pageBodySize = pageSize.clone().applyMargins(72, 72, 72, 72, false);
scale(pdfDocument, pageSize, pageBodySize);
(trecho do teste ScaleToA4testFdaRequiresUseOfEctdFormatAndStandardizedStudyDataInFutureRegulatorySubmissionsSept )