Прежде всего, несколько слов об архитектуре iText, стоящих за некоторыми используемыми вами конструкциями:
Когда вы используете экземпляр Document
для добавления контента в документ, который iText должен автоматически разметить, предполагается, что областьгде iText может макетировать всю страницу за вычетом полей страницы.
Таким образом, если вы добавляете дополнительный материал страницы через другие каналы, кроме Document
, например, как вы делаете в своих NormalPageHeader headerHandler
и PageEndEvent pageEndEvent
это ваша ответственность сделать это за пределами области макета , описанной выше, то есть в областях полей.(Если этот дополнительный материал не является фоновым материалом, например, водяным знаком ...)
Для этого вы должны установить поля достаточно большими, чтобы гарантировать, что ваш дополнительный материал находится на полях.По умолчанию поля страницы установлены на 36pt на каждой стороне страницы, что обычно достаточно для однострочного или нижнего колонтитула, но не совсем для многострочных.
В вашем коде вы создаете заголовок, который требуетпо крайней мере, около 52pt плюс бит, чтобы содержимое iText не коснулось строки заголовка.
Учитывая это, довольно просто вставить данный PdfPage sourcePage
в вашу страницу:
...
NormalPageHeader headerHandler = testPdf.new NormalPageHeader(Paths.get("images").toAbsolutePath() + "\\logo.png", pdfFontMap);
pdfDoc.addEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);
PageEndEvent pageEndEvent = testPdf.new PageEndEvent(Paths.get("images").toAbsolutePath() + "\\FooterLineExternal.png" ,pdfFontMap);
pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, pageEndEvent);
Document doc = new Document(pdfDoc);
doc.setTopMargin(55);
PdfFormXObject xobject = sourcePage.copyAsFormXObject(pdfDoc);
Rectangle xobjectBoundaryBox = xobject.getBBox().toRectangle();
xobject.getPdfObject().put(PdfName.Matrix, new PdfArray(new float[] {1, 0, 0, 1, -xobjectBoundaryBox.getLeft(), -xobjectBoundaryBox.getBottom()}));
Image image = new Image(xobject);
image.setAutoScale(true);
doc.add(image);
doc.close();
...
(выдержка из InsertInSpace helper insertIntoNithinTestFile
)
Если вы используете исходную исходную страницу как есть, приведенный выше код будет вставленэто в том числе все пространство на полях.Если вы не хотите этого, а вместо этого урезаете это пространство, вы можете выполнить следующие действия, чтобы определить фактическую ограничивающую рамку содержимого страницы, уменьшить страницу до этой рамки и перенаправить ее к методу insertIntoNithinTestFile
выше, предполагая, что страницаОбрабатывается 1 из PdfDocument pdfDocument
:
PdfDocumentContentParser contentParser = new PdfDocumentContentParser(pdfDocument);
MarginFinder strategy = contentParser.processContent(1, new MarginFinder());
PdfPage page = pdfDocument.getPage(1);
page.setCropBox(strategy.getBoundingBox());
page.setMediaBox(strategy.getBoundingBox());
insertIntoNithinTestFile(page, "test-InsertIntoNithinTestFile.pdf");
( InsertInSpace test testInsertSimpleTestPdf
)
MarginFinder
- это портiText5 MarginFinder
до iText 7:
public class MarginFinder implements IEventListener {
public Rectangle getBoundingBox() {
return boundingBox != null ? boundingBox.clone() : null;
}
@Override
public void eventOccurred(IEventData data, EventType type) {
if (data instanceof ImageRenderInfo) {
ImageRenderInfo imageData = (ImageRenderInfo) data;
Matrix ctm = imageData.getImageCtm();
for (Vector unitCorner : UNIT_SQUARE_CORNERS) {
Vector corner = unitCorner.cross(ctm);
addToBoundingBox(new Rectangle(corner.get(Vector.I1), corner.get(Vector.I2), 0, 0));
}
} else if (data instanceof TextRenderInfo) {
TextRenderInfo textRenderInfo = (TextRenderInfo) data;
addToBoundingBox(textRenderInfo.getAscentLine().getBoundingRectangle());
addToBoundingBox(textRenderInfo.getDescentLine().getBoundingRectangle());
} else if (data instanceof PathRenderInfo) {
PathRenderInfo renderInfo = (PathRenderInfo) data;
if (renderInfo.getOperation() != PathRenderInfo.NO_OP)
{
Matrix ctm = renderInfo.getCtm();
Path path = renderInfo.getPath();
for (Subpath subpath : path.getSubpaths())
{
for (Point point2d : subpath.getPiecewiseLinearApproximation())
{
Vector vector = new Vector((float)point2d.getX(), (float)point2d.getY(), 1);
vector = vector.cross(ctm);
addToBoundingBox(new Rectangle(vector.get(Vector.I1), vector.get(Vector.I2), 0, 0));
}
}
}
} else if (data != null) {
logger.fine(String.format("Ignored %s event, class %s.", type, data.getClass().getSimpleName()));
} else {
logger.fine(String.format("Ignored %s event with null data.", type));
}
}
@Override
public Set<EventType> getSupportedEvents() {
return null;
}
void addToBoundingBox(Rectangle rectangle) {
if (boundingBox == null)
boundingBox = rectangle.clone();
else
boundingBox = Rectangle.getCommonRectangle(boundingBox, rectangle);
}
Rectangle boundingBox = null;
Logger logger = Logger.getLogger(MarginFinder.class.getName());
static List<Vector> UNIT_SQUARE_CORNERS = Arrays.asList(new Vector(0,0,1), new Vector(1,0,1), new Vector(1,1,1), new Vector(0,1,1));
}
( MarginFinder.java )