Lecture 17: Typesetting I

COSC 225: Algorithms and Visualization

Spring, 2023

Announcements

  1. Assignment 08 not posted, now optional!
  2. No Quiz Today
  3. Final Projects
    • formal announcement by Wednesday
    • group assignments, tentative topic due Friday

Today

Typesetting I: Breaking paragraphs into lines

  1. Intoduction to the problem
  2. Some technology
  3. Activity: greedy line breaking
  4. Can we do better?

What Is Typesetting?

The process of arranging letters and words onto some medium.

Hand Lettering

Persian cuneiform and Malnazar illuminated manuscript

Movable Printed Type

Jikji type and Gutenberg bible

Computer Typesetting

Typesetting Goals?

Question. What goals might we have in typesetting?

Knuth on Typesetting

[We are] primarily concerned with high-quality technical manuscripts. […] If you merely want to produce a passably good document—something acceptable and basically readable but not really beautiful—a simpler system will usually suffice. […T]he goal is to produce the finest quality; this requires more attention to detail, but you will not find it much harder to go the extra distance, and you’ll be able to take special pride in the finished product.

  • Knuth, The TeXBook

Our Basic Task

Breaking paragraphs into lines.

Input: A plain text paragraph.

  • possibly: individual typeset words

Output: locations of line-breaks

  • possibly: placement of words on the page

Goals:

  • readability
  • beauty?
  • ???

Lorem Ipsum

Placeholder text:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do 
eiusmod tempor incididunt ut labore et dolore magna aliqua. 
Felis pellentesque suspendisse tristique in pulvinar erat integer 
pellentesque nunc viverra auctor semper. Tempus eros ullamcorper 
mauris turpis lacinia dictumst consequat proin facilisis et 
conubia curabitur quisque egestas nullam. Nibh erat sodales 
maecenas quis pulvinar auctor imperdiet platea litora id leo. Per 
fusce lectus ex cursus urna fusce scelerisque. Dolor tempus augue 
sit orci elit porttitor ipsum platea erat.

Nonsense Latin, commonly used to demonstrate graphic design

Parameters?

Question. In order to accomplish our task what parameters should we take into account?

How to Break Lines?

Question. Given those parameters, what procedure would you use to find line breaks?

HTML/CSS/JS Stuff

Parameters:

  • original text, TEXT (string)
  • document element
    • TEXT_WIDTH maximum width of text
    • font, size, etc
    • WORD_SEP minimum space between words

What more do we need?

Step 1: Separate Words

Idea. Process TEXT

  • break into words (use whitespace)
  • create an element for each word
  • put elements in an array

Questions.

  • How to break the string?

  • What type of element for each word?

Getting a <span> array

<span> are (default) inline document divisions

function getSpanArray (text) {
    const words = text.split(/\s+/);
    const spans = [];
    for (let word of words) {
	let elt = document.createElement("span");
	elt.innerText = word;
	spans.push(elt);
    }
    return spans;
}

What Next?

We have

  • a <span> array, spans
  • a parent element (say, <p> or <div>)

How to place the <span>s on the page?

for (let s of spans) {
    parent.appendChild(s);
}

The Result

Oof

What do we need to fix and how?

Getting Span Widths

We can get the dimensions of an HTML element with

let width = elt.getBoundingClientRect().width;

…but elt must alread be placed on the document!

Question. How to do this before we’ve decided where to place elt?

A Trick

Create a hidden element

<div id="hidden"></div>

CSS:

#hidden {
    position: absolute;
    visibility: hidden;
}

JavaScript:

const hidden = document.querySelector('#hidden');
for (let s of spans) {
    hidden.appendChild(s);
}

Widths, At Last

Finally, we can get the width of each word (in pixels).

Question. Now What?

New Units

So Far. We’ve mostly measured lengths in pixels (px)

Problem. Space between words (e.g.) should scale with the size of the font.

  • font sizes may change

Built-in Solution. Distance unit em

  • the width of a capital letter ‘M’

Getting the width of an em inside parent in pixels:

const em = parseFloat(getComputedStyle(parent).fontSize);

Activity: Greedy Linebreaking

Your Task

  • download lec17-breaking-lines.zip
  • write a method greedyLines(spans, parent)
    • spans an array of <span> elements, one per word
    • parent an element (<div>) that will contain words
  • words are displayed in lines
  • each line is at most TEXT_WIDTH pixels wide
  • words are separated by 0.5 em space

More:

  • indent first line of the paragraph
  • print “justified” text instead of “ragged right”

Example Output

Suggestions

  1. Use JavaScript to decide where to break lines and create auxiliary elements
  2. Use CSS to actually place the elements
    • display
    • margin
    • justify-content

How’d It Go?

Tricks: Word Spacing in CSS

span {
    margin: 0em 0em 0em 0.5em;
}

span:first-child {
    margin: 0em;
}

.first-line > span:first-child {
    margin: 0em 0em 0em 2em;
}

Fonts

  • Google Fonts demo

Global Parameters/Variables in CSS

:root {
    --light-blue: rgb(200,255,255);
    --mild-yellow: rgb(255, 255, 200);
    /* font-family: 'EB Garamond', serif; */
    font-family: 'Libre Baskerville', serif;
    font-size: 16px;

}
span {
    margin: 0em 0em 0em 0.5em;
    background-color: var(--mild-yellow);
}

For Your Consideration

Can we do a better job of breaking paragraphs into lines?

  • What room is there for practical or aesthetic improvement?