居中文本,x坐标不受尊重

时间:2013-03-29 10:51:17

标签: java pdf pdf-generation pdfbox

我修改了TextToPDF类以检测内容文件中的某些标记。 找到代码中心时,文本居中。

无法正常工作,X坐标似乎不受尊重

当我显示x:coordonate时,我得到: 0

0

18.861816

2.9138184

238.31181

9.933823

68.68582

10.347824

40.14981

在生成的pdf中,第6行应该在第5行之前开始,但是从第5行开始。

238.31181> 9.933823,但pdfbox似乎说9.933823> 238.31181

生成文件的结果 enter image description here

此字符串放在StringReader中,用于createPDFFromText参数。

String rawText = "Children's heart surgery has been suspended with immediate effect at a hospital which is embroiled in a long-running row over the future of paediatric cardiac services in England. \n "
    + "#CENTER#The decision to stop congenital heart surgery at Leeds General Infirmary comes just a day after the High Court quashed plans by the NHS to close its children's unit after ruling the consultation process was flawed.\n "
    + "It follows concerns raised about patients' care including allegations the hospital was avoiding referring children for complex and life-saving treatment at another centre in Newcastle.\n "
    + "Leeds Teaching Hospitals NHS Trust said the temporary measure was being taken to allow an internal review to be conducted following consultation with the Care Quality Commission (CQC).";

代码

public PDDocument createPDFFromText( Reader text ) throws IOException
{
    PDDocument doc = null;
    PDSimpleFont font = PDType1Font.TIMES_ROMAN;
    int fontSize = 12;
    boolean isCentered = false;
    try
    {

        final int margin = 40;
        float height = font.getFontDescriptor().getFontBoundingBox().getHeight()/1000;

        //calculate font height and increase by 5 percent.
        height = height*fontSize*1.05f;
        doc = new PDDocument();
        BufferedReader data = new BufferedReader( text );
        String nextLine = null;
        PDPage page = new PDPage();
        PDPageContentStream contentStream = null;
        float y = -1;
        float maxStringLength = page.getMediaBox().getWidth() - 2*margin;

        // There is a special case of creating a PDF document from an empty string.
        boolean textIsEmpty = true;

        while( (nextLine = data.readLine()) != null )
        {

            // The input text is nonEmpty. New pages will be created and added
            // to the PDF document as they are needed, depending on the length of
            // the text.
            textIsEmpty = false;

            String[] lineWords = nextLine.trim().split( " " );
            int lineIndex = 0;
            while( lineIndex < lineWords.length )
            {
                StringBuffer nextLineToDraw = new StringBuffer();
                float lengthIfUsingNextWord = 0;
                do
                {
                    nextLineToDraw.append( lineWords[lineIndex] );
                    nextLineToDraw.append( " " );
                    lineIndex++;
                    if( lineIndex < lineWords.length )
                    {
                        String lineWithNextWord = nextLineToDraw.toString() + lineWords[lineIndex];
                        lengthIfUsingNextWord =
                            (font.getStringWidth( lineWithNextWord )/1000) * fontSize;
                    }
                }
                while( lineIndex < lineWords.length &&
                       lengthIfUsingNextWord < maxStringLength );
                if( y < margin )
                {
                    // We have crossed the end-of-page boundary and need to extend the
                    // document by another page.
                    page = new PDPage();
                    doc.addPage( page );
                    if( contentStream != null )
                    {
                        contentStream.endText();
                        contentStream.close();
                    }
                    contentStream = new PDPageContentStream(doc, page);
                    contentStream.setFont( font, fontSize );
                    contentStream.beginText();
                    y = page.getMediaBox().getHeight() - margin + height;
                    contentStream.moveTextPositionByAmount(
                        margin, y );

                }
                //System.out.println( "Drawing string at " + x + "," + y );

                if( contentStream == null )
                {
                    throw new IOException( "Error:Expected non-null content stream." );
                }

                String txt = nextLineToDraw.toString();

                if ( txt.indexOf( "#CENTER#" ) != -1 || isCentered )
                {
                    txt = nextLineToDraw.toString().replaceAll( "#CENTER#", "" );

                    PDRectangle pageSize = page.findMediaBox();
                    float stringWidth = font.getStringWidth( txt );
                    float xPosition = ( pageSize.getWidth() - ( 2 * margin ) - ( stringWidth * fontSize ) / 1000f ) / 2f;

                    System.out.println( xPosition );

                    contentStream.moveTextPositionByAmount( xPosition, -height );
                    isCentered = true;
                }
                else
                {
                                            System.out.println( 0);
                    contentStream.moveTextPositionByAmount( 0, -height );
                }

                y -= height;
                contentStream.drawString( nextLineToDraw.toString() );
            }
        }
        if (textIsEmpty)
        {
            doc.addPage(page);
        }

        if( contentStream != null )
        {
            contentStream.endText();
            contentStream.close();
        }
    }
    catch( IOException io )
    {
        if( doc != null )
        {
            doc.close();
        }
        throw io;
    }
    return doc;
}

此处提供了文件结果:http://filebin.ca/br6slMSfOR6/testUnitairePdf.pdf 如您所见,文本未正确居中。

2 个答案:

答案 0 :(得分:2)

问题是(就像@GaborSch在他对他的回答的评论中所猜测的那样)

contentStream.moveTextPositionByAmount()

相对于最后一行工作,而不是相对于某个固定边距。

详细说明:

PDPageContentStream方法moveTextPositionByAmount记录为:

/**
 * The Td operator.
 * @param x The x coordinate.
 * @param y The y coordinate.
 * @throws IOException If there is an error writing to the stream.
 */
public void moveTextPositionByAmount( float x, float y ) throws IOException

Td 操作符依次记为:

  

tx ty Td 移动到下一行的开头,从当前行的开头偏移(tx,ty)。 tx和ty应表示以未缩放的文本空间单位表示的数字。更准确地说,该操作员应执行这些任务:

enter image description here

(参见PDF规范ISO 32000-1:2008,第9.4.2节“文本定位运算符”)

因此,您必须记住使用的xPosition值和

  • 就在行

    之后
    contentStream.drawString( nextLineToDraw.toString() );
    

    插入

    contentStream.moveTextPositionByAmount( -xPosition, 0 );
    

    如果该线居中;

  • 或等到确定下一行文本的moveTextPositionByAmount参数,然后从新x值中减去此前xPosition值。

答案 1 :(得分:0)

也许您正在尝试将所有文​​本块插入到彼此中。

您在循环中调用contentStream.begintText(),但在整个循环之外只调用contentStream.endText()一次。

我不熟悉TextToPDF,只是一个猜测。但在我看来,下一个缩进是正确的,它只相对于前一个块,呈现,因为prevoius块没有正确关闭。

我建议将beginText()endText() s配对,这会有所帮助。