PDF created by iText7 with Header is not accessible - pdf

I created a pdf with iText7. The pdf has a header on each page which consists of two (sometimes more) rows. I added them as in the jump start tutorial, chapter 3.
The problem is, that there are no tags generated, so the screenreader (JAWS) does'nt find the header and blind users can not access it.
I tried to add some tags manually to mimic a table, but that seems to be ignored completly.
Here is my code to create the pdf:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.pdfa.PdfADocument;
public class ITextHeader {
private PdfADocument pdf;
private PdfFont bf;
public static void main(String[] args) throws Exception {
new ITextHeader().createPdf();
}
private void createPdf() throws Exception {
PdfWriter writer = new PdfWriter(new FileOutputStream("header.pdf"));
InputStream icm = new FileInputStream("sRGB_CS_profile.icm");
pdf = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_1A,
new PdfOutputIntent("Custom", "", null, "sRGB IEC61966-2.1", icm));
pdf.setTagged();
bf = PdfFontFactory.createFont("arial.ttf", PdfEncodings.IDENTITY_H);
try (Document pdfDocument = new Document(pdf, PageSize.A4, true)) {
pdfDocument.setMargins(100, 15, 50, 15);
pdf.addEventHandler(PdfDocumentEvent.START_PAGE, this::createHeader);
pdfDocument.add(new Paragraph("Here is the content").setFont(bf).setFontSize(10));
}
}
public void createHeader(Event event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfPage page = docEvent.getPage();
PdfCanvas pdfCanvas = new PdfCanvas(
page.newContentStreamBefore(), page.getResources(), pdf);
pdfCanvas.beginText()
.setFontAndSize(bf, 10)
.beginMarkedContent(PdfName.Table)
.moveText(15, 804)
.beginMarkedContent(PdfName.TR)
.beginMarkedContent(PdfName.TD)
.showText("My Title")
.endMarkedContent() // TD
.moveText(466, 0)
.beginMarkedContent(PdfName.TD)
.showText("Date: 01.01.2022")
.endMarkedContent() // TD
.endMarkedContent() // TR
.moveText(-466, -14)
.beginMarkedContent(PdfName.TR)
.beginMarkedContent(PdfName.TD)
.showText("My Subtitle")
.endMarkedContent() // TD
.moveText(466, 0)
.beginMarkedContent(PdfName.TD)
.showText("Time: 12:30")
.endMarkedContent() // TD
.endMarkedContent() // TR
.endMarkedContent() // TABLE
.endText();
}
}
This is the structure of the pdf as shown by PDF Accessibility Checker:
The Accesibility Checker also complains about not tagged content:

We solved the issue with the following workaround: the header on the first page is rendered as a PDF table, on the following pages we use the canvas to display the text.
This solution is somewhat ankward because we have to implement the headers twice with different techniques, but now JAWS finds at least the header on the first page.

Related

PDFBox insert images inline with TEXT

I am using PDFBox for the first time to generate a PDF. I have a text document which consists of a series of about 40 multi-choice questions generated by my java program. Some of the questions have associated small images which need to be inserted above the question.
For this reason I am converting the text document to a PDF and hope to insert the images on that.
I have managed to insert an image into the PDF document but it underlay’s the text like a background.
I want to place the images in line with the text (as in word format text box, inline).
It seems the insert image classes need an absolute position which will depend on the position of the text.
How can I know where to draw my image?
for info PDFBox 2.0.7.jar
import ExamDatabase.ReadInputFile;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.PDFontFactory;//???look up
import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
import org.apache.pdfbox.pdmodel.font.PDType3Font;
import org.apache.pdfbox.pdmodel.font.PDSimpleFont;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.graphics.image.PDInlineImage;
/**
*
* #author Steve carr
*/
public class HelloWorldPdf1_1_1
{
//runs
/**
* #param args the command line arguments
* #throws java.io.IOException
*/
public static void main(String[] args) throws IOException
{
ReadInputFile fileI = new ReadInputFile();// read plain text file text file
ArrayList<String> localList = fileI.readerNew();
// Create a document and add a page to it
try (PDDocument document = new PDDocument())
{
PDPage page = new PDPage();
document.addPage(page);
// Create a new font1 object selecting one of the PDF base fonts
PDFont font1 = PDType1Font.HELVETICA;//TIMES_ROMAN;
PDFont font2 = PDType1Font.TIMES_ROMAN;
PDFont font3 = PDType1Font.COURIER_BOLD;
try (PDPageContentStream contentStream = new PDPageContentStream(document, page))
{
//Creating PDImageXObject object
PDImageXObject pdImage = PDImageXObject.createFromFile("C:/PdfBox_Examples/CARD00.GIF", document);
//**creating the PDPageContentStream object
//PDPageContentStream contents = new PDPageContentStream(document, page);
//**Drawing the image in the PDF document
contentStream.drawImage(pdImage, 100, 500, 50, 70);//1ST number is horizontal posn from left
//****TEXTTEXTTEXTTEXT
// Define a text content stream using the selected font1, moving the cursor and drawing the text "Hello World"
contentStream.beginText();
contentStream.setFont(font1, 11);
contentStream.newLineAtOffset(0, 0);
contentStream.setCharacterSpacing(0);
contentStream.setWordSpacing(0);
contentStream.setLeading(0);
contentStream.setLeading(14.5f);// this was key for some reason
contentStream.moveTextPositionByAmount(100, 700);// sets the start point of text
System.out.println("localList.size= " + localList.size());//just checking within bounds during testing
String line;
int i;
for (i = 0; i < 138; ++i)
{
System.out.println(localList.get(i));
line = localList.get(i);
contentStream.drawString(line);
contentStream.newLine();
}
contentStream.endText();
//******************************************************
// Make sure that the content stream is closed:
contentStream.close();
}
// Save the results and ensure that the document is properly closed:
document.save("Hello World.pdf");
}
}
}
result output with text written on top of image:
As per this pdf box fix: https://issues.apache.org/jira/browse/PDFBOX-738, transparency is preserved only when rgba is set.so if transparency is preserved it will look as inline with the other text rather than an overlay, so this could be a solution for your first part of the problem ie the overlay issue.
And this example helps you find how to compute the width occupied by a specific text and thus to calculate where to place the image next after the text:
https://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/DetermineTextFitsField.java?revision=1749360&view=markup

Remove the border of a table headerCell itext7 pdf

I am creating a table using itext7.
I can change the color of a regular cell. How can I change the border to Null of a header cell?
I cannot add a check to create a "false" headerCell as the table may be a mutli-column so I would like the cells to be atop each column.
Having this false headerCell would just be on the first cell generated.
I tried:
//does not work.
table.setBorder(null);
//---------------------------does not work.
table.addHeaderCell("one: ").setBorder(Border.NO_BORDER);
table.addHeaderCell("two: ").setBorder(null).addStyle(normal);
table.addHeaderCell("three: ").setBorder(null).addStyle(normal);
Minimal:(just set your location)
package application;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import com.itextpdf.io.font.FontConstants;
import com.itextpdf.kernel.color.Color;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfDocumentInfo;
import com.itextpdf.kernel.pdf.PdfString;
import com.itextpdf.kernel.pdf.PdfViewerPreferences;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.ColumnDocumentRenderer;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.border.Border;
import com.itextpdf.layout.border.SolidBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Text;
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
exportRes();
}
public static void main(String[] args) {
launch(args);
}
public void exportRes() throws IOException{
PdfWriter writer = new PdfWriter(--location--);
PdfDocument pdf = new PdfDocument(writer);
pdf.getCatalog().setLang(new PdfString("en-US"));
pdf.getCatalog().setViewerPreferences(new PdfViewerPreferences().setDisplayDocTitle(true));
PdfDocumentInfo info = pdf.getDocumentInfo();
info.setTitle("List");
Document document = new Document(pdf,PageSize.A4);
PdfFont font = PdfFontFactory.createFont(FontConstants.HELVETICA);
Style normal = new Style();
normal.setFont(font).setFontSize((float) 7.5);
Style notesF = new Style();
notesF.setFont(font).setItalic().setFontSize((float) 7.5);
Style lastNameF = new Style();
lastNameF.setFont(font).setFontSize((float) 7.5).setBold();
Table table = new Table(new float[]{(float) 2,29,10});
table.setWidthPercent(100);
table.setFont(font);
//does not work.
table.setBorder(null);
//---------------------------does not work.
table.addHeaderCell("one: ").setBorder(Border.NO_BORDER);
table.addHeaderCell("two: ").setBorder(null).addStyle(normal);
table.addHeaderCell("three: ").setBorder(null).addStyle(normal);
Cell check = new Cell().add(new Paragraph(" ").addStyle(normal).setFixedLeading(0)).setBorder(new SolidBorder(Color.LIGHT_GRAY, (float) 0.5));
table.addCell(check);
Text lastName = new Text("Name ").setBold().addStyle(lastNameF);
Text address = new Text("address").addStyle(normal);
Cell name = new Cell().add(new Paragraph().add(lastName).add(address)).setBorder(new SolidBorder(Color.LIGHT_GRAY, (float) 0.5));
table.addCell(name);
Cell notes = new Cell().add("notes").addStyle(notesF).setBorder(new SolidBorder(Color.LIGHT_GRAY, (float) 0.5));
table.addCell(notes);
document.add(table);
document.close();
}
}
Your code is almost right. The problem is very simple and can be found in the next line:
table.addHeaderCell("one: ").setBorder(Border.NO_BORDER);
Notice that Table#addHeaderCell method returns Table not Cell object. So then you apply Border.NO_BORDER on Table.
The solution is:
table.addHeaderCell(new Cell().add("one: ").setBorder(Border.NO_BORDER));
Also if you want to set specific border on header/footer (the analog of Table border), write summat table.getHeader().setBorder(your border). Notice also that itext applys table border on header/footer too.
I also want to mention that invoking Table constructor as you do isn't 100% correct if you use itext 7.0.2+. If you want columns widths to be in a ratio 2 29 30 (or any else), call Table(UnitValue.createPercentArray(new float[]{2, 29, 30)) ;

Is there a way to flatten (programatically) a filled in XFA PDF form so it can be opened nicely in browsers?

I have an XFA PDF that is already filled in and now I want to convert it to more compatible format so that it can be opened right in the browsers instead of showing a blank document (bad user experience).
Is there a way to maybe "flatten" (programatically) the XFA PDF so that it will be a straight-up PDF?
I'm using Java and have these imports:
import org.apache.pdfbox.cos.COSStream;
import org.apache.pdfbox.io.RandomAccessBuffer;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDXFA;
And the code is like this:
File sourcePdf = new File(this.manager.getStringValue("SourcePDFFile", data));
File targetPDF = new File(this.manager.getStringValue("TargetPDFFile", data));
try {
PDDocument e = PDDocument.load(sourcePdf);
PDDocumentCatalog docCatalog = e.getDocumentCatalog();
PDAcroForm form = docCatalog.getAcroForm();
PDXFA xfa = form.getXFA();
String s = new String(xfa.getBytes());
String replacementString = IOUtils.toString(data.getDataStream());
s = s.replaceAll("<xfa:data />", replacementString);
COSStream cosout = new COSStream(new RandomAccessBuffer());
OutputStream out = cosout.createUnfilteredStream();
out.write(s.getBytes());
form.setXFA(new PDXFA(cosout));
e.save(targetPDF.getAbsolutePath());
return data;
} catch (Exception var12) {
throw new EIPException("Filling Processor: Unable to fill PDF", var12);
}

JavaFX Separator depend not on the Width of the Class

i would like to get a Separator, which changes his Size with the Size of the Mother-Component.
In my Example, i have a JavaFX Popup and there i add a VBox. To this VBox i add a HBox. And this HBox has a Label, a Speparator and a Button.
Now i would like to have that the Button is on the Right End and the Label is on the Left End of the HBox. I think i have to use a Separator between these components to get the Space.
How can i handle it...
I made something like this, but it does not work.
// Box for the Headline
HBox headLine = new HBox();
headLine.setPadding(new Insets(5, 5, 5, 5));
// Label with the HeadLine Description in
final Label heading = new Label(headLineText);
heading.getStyleClass().addAll("popup-label-name");
// Close Button
close = new Button("X");
close.setVisible(false);
closeButtonHandler();
// Creates an invisble Separator1
Separator sep = new Separator(Orientation.HORIZONTAL);
sep.setVisible(false);
sep.widthProperty().add(m_container.widthProperty().get());
close.getStyleClass().addAll("popup-button", "popup-button-color");
// Adds to the Headline the Data
headLine.getChildren().addAll(heading, sep, close);
The Variable m_container is the VBox! How can i handle it?
Thanks for your help :)
The simplest way (if not using a different container like AnchorPane) is to insert an invisible, but expandible 'space' object:
void testLabelSpace(HBox box) {
Text first = new Text("first");
Text second = new Text("second");
Node space = new HBox();
HBox.setHgrow(space, Priority.ALWAYS);
box.getChildren().addAll(first, space, second);
}
If I understand the question correctly, you just want blank space between the label and the button. Just tell the Label always to grow horizontally, and set its maximum width to allow it to grow to any size:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
public class HBoxExample extends Application {
#Override
public void start(Stage primaryStage) {
HBox hbox = new HBox();
Label label = new Label("Label");
Button button = new Button("Button");
HBox.setHgrow(label, Priority.ALWAYS);
label.setMaxWidth(Double.MAX_VALUE);
hbox.getChildren().addAll(label, button);
primaryStage.setScene(new Scene(hbox, 350, 75));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

How to Add Text and Image Both in a SWT LABEL

Is there any way to add Text and Image in SWT label in a single line.
Once I add image, text goes off.
No you can't have an image and text simultaneously in a Label (unless you custom draw it). Else use org.eclipse.swt.custom.CLabel:
Code:
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class LabelTest {
public static void main(String[] args)
{
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
Image image = new Image(display, "next.png");
CLabel label = new CLabel(shell, SWT.BORDER);
label.setImage(image);
label.setText("This is a CLabel !!");
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
if(image != null)
{
image.dispose();
image = null;
}
display.dispose();
}
}
Output:
Button click to open FileDialog Box and selected any image to display with text on specific label.
import org.eclipse.swt.custom.CLabel
A Label which supports aligned text and/or an image and different border styles.
I hope this answer is usefull.
please visit this page:
How to load image to view in RCP?
Yes, using an intermediary composite with the right layout
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new RowLayout(SWT.HORIZONTAL));
Label imageLabel = new Label(composite, SWT.NONE);
mageLabel.setImage(...);
Label textLabel = new Label(composite, SWT.NONE);
textLabel.setText(...)