Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 59 additions & 5 deletions openpdf-core/src/main/java/org/openpdf/text/pdf/ColumnText.java
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,13 @@ public class ColumnText {
*/
private boolean strictWordWrapping = false;

/**
* Custom baseline Y position for the first line. When set (not NaN), this takes precedence
* over the normal yLine - leading calculation for positioning the first line.
* Subsequent lines use normal leading calculations.
*/
private float customFirstLineBaselineY = Float.NaN;

/**
* Creates a <CODE>ColumnText</CODE>.
*
Expand Down Expand Up @@ -509,6 +516,7 @@ protected void setSimpleVars(ColumnText org) {
filledWidth = org.filledWidth;
adjustFirstLine = org.adjustFirstLine;
strictWordWrapping = org.strictWordWrapping;
customFirstLineBaselineY = org.customFirstLineBaselineY;
}

private void addWaitingPhrase() {
Expand Down Expand Up @@ -1050,12 +1058,27 @@ public int go(boolean simulate) throws DocumentException {
} else {
currentLeading = Math.max(fixedLeading + maxSize[0] * multipliedLeading, maxSize[1]);
}
if (yLine > maxY || yLine - currentLeading < minY) {
status = NO_MORE_COLUMN;
bidiLine.restore();
break;

// Check if custom first line baseline is set and this is the first line
if (!Float.isNaN(customFirstLineBaselineY) && Float.isNaN(firstLineY)) {
// Use custom baseline for first line
yLine = customFirstLineBaselineY;
// Validate that the custom baseline is within column bounds
if (yLine > maxY || yLine < minY) {
status = NO_MORE_COLUMN;
bidiLine.restore();
break;
}
} else {
// Normal behavior: subtract leading from yLine
if (yLine > maxY || yLine - currentLeading < minY) {
status = NO_MORE_COLUMN;
bidiLine.restore();
break;
}
yLine -= currentLeading;
}
yLine -= currentLeading;

if (!simulate && !dirty) {
text.beginText();
dirty = true;
Expand Down Expand Up @@ -1764,4 +1787,35 @@ public boolean isStrictWordWrapping() {
public void setStrictWordWrapping(boolean strictWordWrapping) {
this.strictWordWrapping = strictWordWrapping;
}

/**
* Sets a custom baseline Y position for the first line in the column.
* When set, this takes precedence over the normal yLine - leading calculation
* for positioning the first line. Subsequent lines continue with normal leading.
* This provides explicit control over first-line placement without requiring
* knowledge of internal leading/ascender adjustments.
*
* @param baselineY the Y coordinate where the baseline of the first line should be positioned.
* Must be within the column bounds (between minY and maxY).
*/
public void setFirstLineBaselineY(float baselineY) {
this.customFirstLineBaselineY = baselineY;
}

/**
* Gets the custom first line baseline Y position if set.
*
* @return the custom first line baseline Y, or NaN if not set
*/
public float getFirstLineBaselineY() {
return customFirstLineBaselineY;
}

/**
* Clears the custom first line baseline Y setting, reverting to normal
* yLine - leading calculation for first-line positioning.
*/
public void clearFirstLineBaselineY() {
this.customFirstLineBaselineY = Float.NaN;
}
}
Loading