Typesetting I: Breaking paragraphs into lines
The process of arranging letters and words onto some medium.

Persian cuneiform and Malnazar illuminated manuscript

Jikji type and Gutenberg bible

Question. What goals might we have in 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.
Breaking paragraphs into lines.
Input: A plain text paragraph.
Output: locations of line-breaks
Goals:
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
Question. In order to accomplish our task what parameters should we take into account?
Question. Given those parameters, what procedure would you use to find line breaks?
Parameters:
TEXT (string)document element
TEXT_WIDTH maximum width of textWORD_SEP minimum space between wordsWhat more do we need?
Idea. Process TEXT
Questions.
How to break the string?
What type of element for each word?
<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;
}
We have
<span> array, spans
parent element (say, <p> or <div>)How to place the <span>s on the page?
for (let s of spans) {
parent.appendChild(s);
}

What do we need to fix and how?
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?
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);
}
Finally, we can get the width of each word (in pixels).
Question. Now What?
So Far. We’ve mostly measured lengths in pixels (px)
Problem. Space between words (e.g.) should scale with the size of the font.
Built-in Solution. Distance unit em
Getting the width of an em inside parent in pixels:
const em = parseFloat(getComputedStyle(parent).fontSize);
lec17-breaking-lines.zip
greedyLines(spans, parent)
spans an array of <span> elements, one per wordparent an element (<div>) that will contain wordsTEXT_WIDTH pixels wide0.5 em spaceMore:

displaymarginjustify-contentspan {
margin: 0em 0em 0em 0.5em;
}
span:first-child {
margin: 0em;
}
.first-line > span:first-child {
margin: 0em 0em 0em 2em;
}
: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);
}
Can we do a better job of breaking paragraphs into lines?