Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

API to set custom first-line baseline Y in ColumnText (e.g., setFirstLineBaselineY / setFirstLineOffsetFromTop) #1430

Open
@balaji-pc

Description

When placing text with ColumnText in a rectangular area, it is hard to precisely control the baseline Y of the first rendered line inside the column. Today, the first line’s baseline is derived from yLine and the effective leading (yLine − leading). In practice, this becomes non‐intuitive and error‐prone when:
setSimpleColumn resets yLine to the top (ury), forcing extra calculations.

  • Effective leading can be a mix of fixed and multiplied leading.
  • Flags like setUseAscender and setAdjustFirstLine can affect first-line placement.
  • Switching between addText(...) and addElement(Paragraph/...) changes how first-line spacing behaves.

The result is that aligning the first line to an exact baseline Y (for forms, labels, receipts, or precise grid layouts) requires trial‐and‐error and knowledge of several interacting flags, rather than a simple, explicit API.

Note:
ColumnText does expose setYLine(float) and documents that "The line will be written to yLine − leading"
ColumnText.java . However, this still requires callers to precompute the correct yLine from a desired baseline and the effective leading, and to account for ascender/first‐line adjustments and composite vs. simple text flows.

Suggested Solution:
Introduce an explicit and ergonomic way to set the first line’s baseline Y inside the column, independent from internal leading/ascender logic. For example:

  1. Compute the firstLine without currentLeading
  2. A direct setter:
    - setFirstLineBaselineY(float baselineY)
    - Guarantees the first line’s baseline equals baselineY, regardless of setUseAscender, setAdjustFirstLine,
    fixed/multiplied leading, or whether the content was added via addText or addElement.
  3. A relative alternative:
    - setFirstLineOffsetFromTop(float offset)
    - Starts the first line’s baseline at (ury − offset) inside the current simple column.
  4. an overload to setSimpleColumn:
    - setSimpleColumn(llx, lly, urx, ury, float firstLineBaselineY)
    - setSimpleColumn(llx, lly, urx, ury, float offsetFromTop, boolean offsetIsFromTop)

Additional notes:

 - This API should only control the first line; subsequent lines continue with normal leading and pagination.
 - Document clear precedence rules vs. setYLine, setUseAscender, setAdjustFirstLine, and leading.
 - Provide examples for both addText(...) and addElement(...) usage.

Current feature example

 `PdfContentByte cb = writer.getDirectContent();
 ColumnText ct = new ColumnText(cb);
 float llx = 50f, lly = 500f, urx = 300f, ury = 700f;
 ct.setSimpleColumn(llx, lly, urx, ury);
 ct.setUseAscender(false);
 
 float dAscent =font.getBaseFont.getAscentPoint("d", font.getSize);
 float baseline = ury-dAscent
 
 // We want firstYLine == baseline but ColumnText writes firstYLine = yLine - leading
 ct.setYLine(baseline); //Note: must be yLine < ury && yLine > lly
 Chunk chunk = new Chunk("Hello, world\nWelcome to OpenPdf", font);
 chunk.setCharacterSpacing(0.4f);
 chunk.setHorizontalScaling(1f);
 Paragraph paragraph = new Paragraph(chunk)
 paragraph.setLeading(14f)
 ct.addText(paragraph);
 ct.go();`

To be short:

Actual:
yLine = ury - dAscent
firstYLine = (ury - dAscent) - currentLeading = 694.68 - 14 = 680.68

Expected:
dAscent = 5.32f
baseline(yLine) = ury - dAscent
firstYline = yLine = 694.68

Your real name
Balaji

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

        AltStyle によって変換されたページ (->オリジナル) /