javapdfbox

There is a stroke parameter for define where draw stroke on PDFBOX?


I work with PDFBox now, and I'm trying to draw a polygon with a big border stroke using the fillAndStroke() method in PDPageContentStream. Actually it works with a stroke in center mode (half inside and half outside the polygon).

How can I specify the stroke type inside or outside the polygon like I can do in JavaFX with this kind of code.

Thank you for your help.

// Create a polygon
Polygon polygon = new Polygon();
polygon.getPoints().addAll(
       50.0, 150.0,  // Point 1 (x, y)
       150.0, 50.0,  // Point 2 (x, y)
       250.0, 150.0, // Point 3 (x, y)
       150.0, 250.0  // Point 4 (x, y)
);
polygon.setFill(Color.LIGHTBLUE);
polygon.setStroke(Color.BLACK);
polygon.setStrokeWidth(3);
// Here we specify the stroke type to inside
polygon.setStrokeType(StrokeType.INSIDE);

I search help in documentation without success, currently I use the PDFBox version: 2.0.25.


Solution

  • The methods the PDFBox class PDPageContentStream offers correspond to the operations defined by the PDF standard for content streams. Consequentially, the docs you are looking for are the ISO 32000 parts.

    Unfortunately, you'll find there that PDF does not have anything like the StrokeType options of JavaFX. Nonetheless, you can emulate the effect using clip paths, e.g. as follows:

    Stroke type "center"

    This is the mode PDF always uses. Thus, no clip paths are necessary:

    canvas.moveTo(50, 150);
    canvas.lineTo(150, 50);
    canvas.lineTo(250, 150);
    canvas.lineTo(150, 250);
    canvas.closeAndFillAndStroke();
    

    (DrawPolygons method drawPolygonCenterStroke)

    Stroke type "inside"

    To emulate this we set a clip path along the polygon border.

    canvas.saveGraphicsState();
    
    canvas.moveTo(50, 150);
    canvas.lineTo(150, 50);
    canvas.lineTo(250, 150);
    canvas.lineTo(150, 250);
    canvas.closePath();
    canvas.clip();
    
    canvas.moveTo(50, 150);
    canvas.lineTo(150, 50);
    canvas.lineTo(250, 150);
    canvas.lineTo(150, 250);
    canvas.closeAndFillAndStroke();
    
    canvas.restoreGraphicsState();
    

    (DrawPolygons method drawPolygonInsideStroke)

    Stroke type "outside"

    To emulate this we first fill the inside of the full polygon, then set the clip path to include the rest of the page except the polygon, and finally stroke the polygon border.

    canvas.moveTo(50, 150);
    canvas.lineTo(150, 50);
    canvas.lineTo(250, 150);
    canvas.lineTo(150, 250);
    canvas.fill();
    
    canvas.saveGraphicsState();
    
    canvas.addRect(0, 0, 300, 300);
    canvas.moveTo(50, 150);
    canvas.lineTo(150, 50);
    canvas.lineTo(250, 150);
    canvas.lineTo(150, 250);
    canvas.closePath();
    canvas.clipEvenOdd();
    
    canvas.moveTo(50, 150);
    canvas.lineTo(150, 50);
    canvas.lineTo(250, 150);
    canvas.lineTo(150, 250);
    canvas.closeAndStroke();
    
    canvas.restoreGraphicsState();
    

    (DrawPolygons method drawPolygonOutsideStroke)

    Result

    screenshot

    Obviously in the inside and outside cases half the stroke line is cut off. Thus, to achieve a certain stroke width, you have to set the line width to twice that value.