Skip to content
Open
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
12 changes: 12 additions & 0 deletions src/core/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,18 @@ export const CHAR = 'CHAR';
* @final
*/
export const WORD = 'WORD';
/**
* @typedef {'PRETTY'} PRETTY
* @property {PRETTY} PRETTY
* @final
*/
export const PRETTY = 'PRETTY';
/**
* @typedef {'BALANCE'} BALANCE
* @property {BALANCE} BALANCE
* @final
*/
export const BALANCE = 'BALANCE';

// TYPOGRAPHY-INTERNAL
export const _DEFAULT_TEXT_FILL = '#000000';
Expand Down
42 changes: 42 additions & 0 deletions src/type/textCore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2387,6 +2387,48 @@ function textCore(p5, fn) {
opts = {}
) {

// Handle PRETTY/BALANCE with DP algorithm
if (textWrap === fn.PRETTY || textWrap === fn.BALANCE) {
let newLines = [];
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
const wordsArr = lines[lineIndex].split(' ').filter(s => s.length > 0);
const spaceW = this._textWidthSingle(' ');
const N = wordsArr.length;
const widths = wordsArr.map(s => this._textWidthSingle(s));

// DP arrays
const dp = new Array(N + 1).fill(Infinity);
const next = new Array(N + 1).fill(-1);
dp[N] = 0;

// DP algorithm to minimize raggedness
for (let i = N - 1; i >= 0; i--) {
let sum = 0;
for (let j = i; j < N; j++) {
sum += widths[j];
const gaps = j - i;
const total = sum + gaps * spaceW;
if (total > maxWidth) break;
const slack = maxWidth - total;
const cost = (j === N - 1 ? 0 : slack * slack) + dp[j + 1];
if (cost < dp[i]) {
dp[i] = cost;
next[i] = j + 1;
}
}
}

// Reconstruct lines
let i = 0;
while (i < N) {
const j = next[i] > 0 ? next[i] : i + 1;
newLines.push(wordsArr.slice(i, j).join(' '));
i = j;
}
}
return newLines;
}

let splitter = opts.splitChar ?? (textWrap === fn.WORD ? ' ' : '');
let line, testLine, testWidth, words, newLines = [];

Expand Down
47 changes: 47 additions & 0 deletions test/manual-test-examples/type/pretty-sketch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
function setup() {
createCanvas(800, 600);
background(255);

let sampleText = 'This is a sample text that will be wrapped using the new PRETTY and BALANCE modes. It should result in more balanced line lengths compared to standard WORD wrapping.';
let boxWidth = 200;
let boxHeight = 150;

// Test 1: WORD wrap (standard)
fill(0);
textSize(16);
textAlign(LEFT, TOP);
textWrap(WORD);

stroke(200);
noFill();
rect(50, 50, boxWidth, boxHeight);

fill(0);
noStroke();
text('WORD wrap:', 50, 30);
text(sampleText, 50, 50, boxWidth, boxHeight);

// Test 2: PRETTY wrap
stroke(200);
noFill();
rect(300, 50, boxWidth, boxHeight);

fill(0);
noStroke();
textWrap(PRETTY);
text('PRETTY wrap:', 300, 30);
text(sampleText, 300, 50, boxWidth, boxHeight);

// Test 3: BALANCE wrap (alias for PRETTY)
stroke(200);
noFill();
rect(550, 50, boxWidth, boxHeight);

fill(0);
noStroke();
textWrap(BALANCE);
text('BALANCE wrap:', 550, 30);
text(sampleText, 550, 50, boxWidth, boxHeight);

noLoop();
}
10 changes: 10 additions & 0 deletions test/manual-test-examples/type/pretty-test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>PRETTY/BALANCE TextWrap Test</title>
<script src="../../../dist/p5.js"></script>
<script src="pretty-sketch.js"></script>
</head>
<body>
</body>
</html>