Lecture 18: Typesetting II

COSC 225: Algorithms and Visualization

Spring, 2023

Final Project Timeline

  • Friday, April 14: Group/Project registration
  • Monday, May 1: Working prototype, critique in class
  • Wednesday, May 10: Final submission
  • Friday, May 19: Peer reviews due

Today

Typesetting II: Breaking paragraphs into lines

  1. Recap: greedy line breaking
  2. Quantifying “raggedness”
  3. Activity: greedy line breaking
  4. Finding optimal line breaks

Last Time

Breaking paragraphs into lines

Input:

  • TEXT as a string
  • LINE_WIDTH

Output:

  • Placement of each word from TEXT typeset on the screen

Requirement

  • No line of typeset text is wider than LINE_WIDTH

Example Input

Example Output

Greedy Breaking Procedure

Idea:

  • scan through words of text sequentially
  • add words to the current line until adding next word would exceed LINE_WIDTH
  • start a new line with next word

Details

  • dealing with first word of paragraph (paragraph indent)
  • dealing with first word of other lines (no indent)
  • dealing with last line

Greedy Breaking Code

let curLine = createLine();
for (let s of spans) {
  let width = s.getBoundingClientRect().width;
  if (!firstWord) { width += WORD_SEP * em; }
  if (curWidth + width <= TEXT_WIDTH) {
    curLine.appendChild(s);
    curWidth += width; firstWord = false;
  } else {
    parent.appendChild(curLine);
    curLine = createLine();
    curLine.appendChild(s);
    curWidth = width - WORD_SEP * em;}}

Some Questions

  1. Is there a sensible alternative method for choosing line breaks?
  2. What “better” outcomes might we want?

Critique This Paragraph

Is This Better?

Quantifying Raggedness

Aesthetic Goal. Minimize the raggedness of the paragraph.

Question. How to quantify raggedness?

Knuth, Again

Associate a penalty to each line break:

  • the excess $x$ is the amount of trailing whitespace
  • the penalty of the line is $x^2$

The penalty of the whole paragraph is the sum of penalties of all of the lines excluding the last line.

Penalty Example

Our Goal

Find the line breaks for the paragraph that minimize the total penalty of the paragraph.

Why This Penalty

Question. Why is a penalty of $x^2$ sensible? How does penalty relate to raggedness?

Activity

Typeset a short paragraph by hand!

Greedy Penalty

TODAY WE WILL TRY TRY AGAIN

Smaller Penalty?

TODAY WE WILL TRY TRY AGAIN

Greedy Penalty Example

Optimal Penalty Example

An Algorithmic Challenge

Input.

  • array of word lengths
  • whitespace parameters
  • text width

Output.

  • locations of line breaks that will minimize the total penalty of the paragraph

Question

How can we find the optimal line breaks given the input parameters?

A Basic Task

Given indices i and j with i < j, what is the penalty of a line containing words w[i], w[i+1],..., w[j]

  • call this penalty(i, j)

Question. Must we compute penalty(i, j) for all i and j?

Two Line Penalty

Question. Suppose we know penalty[0, i] for all i up to j. How could we find the minimum penalty line break for the first two lines setting words 0..j?

More Generally

Compute: array minPenalties

  • minPenalties[j] stores the minimum total penalty of line breaks ending with a line break at j.

Question. Given minPenalties[0..j-1] and penalty(i, j), how can we determine minPenalty[j]?

Bootstrapping

Question. Given minPenalties[0..j-1] and penalty(i, j), how can we determine minPenalty[j]?

Observe. The minimal penalty of breaking at i and j is:

  • minPenalty[i-1] + penalty(i, j)

So. The minimum possible penalty of breaking at j is the minimum of:

minPenalties[j-1] + penalty(j, j)
minPenalties[j-2] + penalty(j-1, j)
minPenalties[j-3] + penalty(j-2, j)
minPenalties[j-4] + penalty(j-3, j)
...

A Name

This technique for finding the optimal solution is called dynamic programming

Exercise

Find the minimum penalty line breaking for typesetting TODAY WE WILL TRY TRY AGAIN in a paragraph of line width 8.

Line Breaking Demo