A first attempt to wrap paragraphs

In the last chapter, we justified text, but only one line at the time. In this chapter, we will try to wrap an entire paragraph to create the lines. Normally, this kind algorithms do not run in PostScript, but we can program it in PostScript.

There are many sophisticated algorithms for this, including the Knuth-Plass line-breaking algorithm that optimize the spaces playing with the knowledge of all lines and using also hyphenation.

We keep it very simple. Our algorithm works like a typewriter. We write each word after another and when we see that the next word does not fit into the line width, we go to the next line.

First, we need some operators. neg negates a number (-1 mul), roll allows to access deeper elements of the stack by rolling the top elements of the stack and newpath explicitly starts a new path.

Javascript Editor

This is quite a program, therefore we try also to document it with comments. A well structured PostScript program separates the definition of operators (the prologue) from the actual content.

For each operator, we write a comment line that describes the stack input on the left and the stack output of the left.

We need to define max because there is actually no PostScript operator for this. This is rather easy. We copy the 2 top elements of the stack, compare and then keep one element and pop the other.

We already have defined countblanks and justifyshow. They are straightforward. We compare the actual width with the target width, divide the difference by the number of blanks. Here we need max, because we do not want to divide by zero if there are no blanks.

showjustifyblock at the end is also straightforward, combining wordwrap with justifyshow.

The main piece is wraptext. We search the next word and calculate the stringwidth and add it to the linewidth. If it is smaller than the maximal width, we add spacewidth and count also the characters. At the end, we push on the stack the text after (post), the target width and the selected text. Wraptext can then be reused to produce one line at a time.

Javascript Editor

The result works but it is not very pretty for short lines. You see the spaces. We will not start to hyphenate but try a second algorithm to wrap which is still rather simple. Above we only enlarged the space. But we also have the option to make the space smaller. Let's permit the space to shrink by 50% also.

So when it is too big, we check a second time if the text matches with the word and half the space width, we pass.

Javascript Editor

Well, the difference is subtle. The first line includes "by", but the big spaces in the lower lines are inevitable with the long words, when you cannot hyphenate them.

The current code base is now 2021 lines. I made some changes to the console, cutting long texts and two reference count errors. ps20240828.js

My Journey to PostScript