Repository: danfickle/openhtmltopdf

Issue #39: Avoid line break between html elements and text
Created: 2016-09-30T13:49:44Z
Considering the following example:
<!DOCTYPE html>
<html>
<meta charset="utf8" />
<head>
</head>
<body>
some long text… (<span class="keyword">example</span>) …some long text… «&nbsp;<span class="keyword">example2</span>&nbsp;» some long text… <i>example3</i>.
</body>
</html>

Firefox, Safari, Chrome will never break between the texts in spans and the (immediate-)surrounding characters.
But, depending on the position of the text, openhtmltopdf may put a line break between:

"(" and "example" or "example" and ")"
same between "«"/"»" and "example2"
same between example3 and "."

This results in not properly formatted text.
The texts here in the spans should be considered as being on the same level as the surrounding text.
More generally, this should probably be the default behavior for any inline tags.

Duplicate issue #680: [Accessibility][ScreenReader]Problem with bold, italics, underline text in generated PDF
Created: 2021-03-30T15:10:49Z
EDIT: I tested the HTML fragment (in the end of post) in https://sandbox.openhtmltopdf.com/ and it shows the same behavior I described (try to select the line to see it happen).
Hello,
When we have some text with formatting (bold), the resulting PDF is kind of weird. The formatted text shows correctly in the PDF, but when I select the text (as seen in the image below), I select the start of the line, then the end, and finally the formatted text. Inspecting in Firefox, the order seems incorrect to me (it is the same I described for selection):

The same problem occurs when a user tries to use a screen reader (such as NVDA) to read the text (it reads in the wrong order).
I want to know if the problem is related to this lib or maybe it is in the PDFBox
Below, the code used to generate the PDF:
    private static final String ESTILO_BASE = "<style> "
            + " body { word-wrap: break-word; font-family: 'Courier New', Courier, monospace; }"
            + " table { width: 100% !important } "
            + " @page {margin-bottom: 1.5cm; margin-top: 4.5cm; margin-left: 2.6cm; margin-right: 1cm;}</style>";
    private static final String CABECALHO_XHTML = "<!DOCTYPE html [\n" + "  <!ENTITY nbsp \"&#160;\">\n" + "]>\n";

public byte[] obterPdf(DocumentoParaAssinaturaDto documentoDto, String produtorDocumento) {
        String idProcessoDocumento = documentoDto.getIdProcessoDocumentoCurto();
        ByteArrayOutputStream streamPdfa = new ByteArrayOutputStream();
        try {
            byte[] html = Base64.decodeBase64(documentoDto.getDocumentoBinarioBase64());
            OrientacaoDocumentoHTMLEnum orientacaoDocumento = documentoDto.getOrientacaoDocumento();
            PdfRendererBuilder geradorPdf = new PdfRendererBuilder();
            String htmlConteudo = ESTILO_BASE + orientacaoDocumento.getCSS()
                    + new String(html, StandardCharsets.ISO_8859_1);
            Document htmlDoc = Jsoup.parse(htmlConteudo);
            htmlDoc.outputSettings().syntax(Document.OutputSettings.Syntax.xml);
            String htmlConteudoAjustado = new HTMLLimpezaServico().limpar(htmlDoc);
            // Deve ser incluido o doctype com a entity &nbsp no topo do XHTML para o gerador funcionar
            htmlConteudoAjustado = CABECALHO_XHTML + htmlConteudoAjustado;
            
            geradorPdf.withProducer(produtorDocumento);
            geradorPdf.useFastMode();
            geradorPdf.withHtmlContent(htmlConteudoAjustado, "");
            geradorPdf.toStream(streamPdfa);
            geradorPdf.run();
        } catch (Exception e) {
            throw new ConversaoHtmlParaPdfException(MensagensAssinaturaEnum.ERRO_CONVERSAO_HTML_PDF, e,
                    idProcessoDocumento);
        }
        
        return streamPdfa.toByteArray();
    }
the html used to that image is:
<p style="font-family:'Courier New', Courier, monospace;font-size:12pt;line-height:1.5;text-align:justify;text-indent:3cm;">Em relação ao <strong>crédito remanescente da autora</strong>, determino a transferência do numerário para a conta indicada na petição de ID</p>
thanks in advance and congrats for this work!
A. Lucas

Closing comment (2021-03-30T15:32:30Z): After looking other issues, maybe this is related to #39 , although it does not seem to be the exactly same problem.