Skip to content

specifying x-coord does not position in absolute space #1641

Open

Description

@N247S

Bug Report

Description of the problem

What I noticed is that the x (and potentially the y coord) is not an absolute position in the text function when 'continued' is set to true
As far as I could read there is no mention of relativity of the coord-position in relation to the continuedflag, but maybe I misunderstood the API.

I know a workaround already, but I would love to know where this relativity is comming from (i.e. where does it anchor to?). As when I set x of the second text to 0 it does not line up with the first text on the same line

Code sample

// create a document and pipe to a blob
var doc = new PDFDocument();
var stream = doc.pipe(blobStream());

// this should line up both the first and second text on each line
doc.text('testing',
{
    continued: true
});
doc.text('test', 200, undefined);
doc.text('testing out',
{
    continued: true
});
doc.text('test', 200, undefined);

doc.moveDown().moveDown();

// this is a work around which I would expect with the above code
const x = doc.x
doc.text('testing', x, undefined);
doc.moveUp();
doc.text('test', 200, undefined);
doc.text('testing out', x, undefined);
doc.moveUp();
doc.text('lolz', 200, undefined);


// end and display the document in the iframe to the right
doc.end();
stream.on('finish', function() {
  iframe.src = stream.toBlobURL('application/pdf');
});

Your environment

Currently (18-08-2025) present on the online version of:
https://pdfkit.org/examples/browserify/browser.html
Not sure which version it is using.

Activity

  1. JamBalaya56562 commented on Jul 7, 2026

    @JamBalaya56562

    I believe this is working as intended, so this could probably be closed.

    With continued: true, the following segment is laid out inline, continuing the text flow from where the previous segment ended. The x you pass to a continued segment is applied on top of that inline offset, so it won't land at an absolute x — that's by design (it's what lets you change styling mid-paragraph). If you need each segment at an absolute x, use separate (non-continued) text() calls with explicit coordinates instead.

    You can verify both behaviors on the interactive demo (http://pdfkit.org/demo/browser.html) — I drew a guide line at x = 300 so it's easy to see:

    // reference guide at x = 300
    doc.moveTo(300, 60).lineTo(300, 240).stroke('#bbb');
    doc.fontSize(13).fillColor('black');
    
    // (A) continued:true — the x:300 on the 2nd call is NOT absolute;
    //     the segment keeps flowing inline (lands to the RIGHT of the guide)
    doc.text('First. ', 100, 100, { continued: true });
    doc.text('Second — requested x:300', 300, 100);
    
    // (B) separate text() calls — absolute x:300 IS honored (sits ON the guide)
    doc.text('First. ', 100, 160);
    doc.text('Second — absolute x:300', 300, 160);

    Row (A) ignores the requested x:300 and continues inline; row (B) lands exactly on the x:300 guide. So this looks like expected behavior rather than a bug, and could be closed.

  2. N247S commented on Jul 10, 2026

    @N247S
    Author

    Well, that explains why it does what it does. But honestly very confusing/counterintuïtive.

    I get why it would 'continue' the next segment, but I would expect that behavior when continued is set to true on the second-calls. When the continued flag is not present I would expect it to ignore all previous states and behave like it is a blank page (i.e. place things at absolute coordinates when given).

    It makes the following codeflow very awkward:

    const texts = getTextParts();
    for(const t of texts)
    	doc.text(t, { continued: true });
    
    doc.text(someText, 400, undefined);

    As I would have to set continued to false for the last call in the loop.

    The same is true when deligating content-portions to separate functions.
    It is very difficult to not 'bleed' any style or positioning info beyond its own scope with this kind of behavior.

    So this either needs proper documentation, or a rethink of how pdfkit should behave and/or 'bleed state/style/info' for 'next draw-calls' IMO.

  3. JamBalaya56562 commented on Jul 10, 2026

    @JamBalaya56562

    You're right — I dug into the source and your point holds up. continued is a forward-looking flag, so the call right after a continued run keeps flowing inline even with an explicit x, which offsets it instead of treating it as absolute.

    I've opened #1748: a non-continued text() call given an explicit x/y now starts fresh at that absolute position (existing rich-text sequences, which pass no coordinates, are unchanged). It also documents the behavior. Thanks for pushing back on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions