Accept
Walk back with the blue arrow until we reach the first letter of the word.
lay out text
reset
layout When whole contents isEmpty not Do maxHeight := whole first ascent. maxDescent := whole first descent. missingHeight := 0. whole first pivotBecomes ((whole shape leftAtY 0) , maxHeight) + inset. rule tell whole first successor to 'place'. When Always Do rule tellLater rule to 'showSelection'. rule processActions.
whole contents isEmpty not
maxHeight := whole first ascent. maxDescent := whole first descent. missingHeight := 0. whole first pivotBecomes ((whole shape leftAtY 0) , maxHeight) + inset. rule tell whole first successor to 'place'.
pivotBecomes
leftAtY
tell
to
Always
rule tellLater rule to 'showSelection'. rule processActions.
tellLater
to
Accept
Move that letter to the next line. Resume placing letters to the right of the "o", as indicated by the red arrow. Notice that all letters in the word "over" are placed more than once during the layout.
Noticing going beyond the right margin isClipped is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
sClipped is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
backToWordStart When Always Do letterToMove := self startOfWord me. When self isStartOfLine letterToMove index Do "Word takes entire line, break at the clipped character" letterToMove := me. When Always Do maxHeight := letterToMove ascent. letterToMove pivotYIncreaseBy maxHeight + maxDescent + 2. letterToMove pivotPosition ((whole shape leftAtY letterToMove pivotPosition y) + inset x) , letterToMove pivotPosition y. missingHeight := 0. rule tell letterToMove successor to 'place'.
Always
letterToMove := self startOfWord me.
startOfWord
self isStartOfLine letterToMove index
isStartOfLine
"Word takes entire line, break at the clipped character" letterToMove := me.
Always
maxHeight := letterToMove ascent. letterToMove pivotYIncreaseBy maxHeight + maxDescent + 2. letterToMove pivotPosition ((whole shape leftAtY letterToMove pivotPosition y) + inset x) , letterToMove pivotPosition y. missingHeight := 0. rule tell letterToMove successor to 'place'.
pivotYIncreaseBy
pivotPosition
leftAtY
tell
to
lay out text
To layout the text in the field, place the next letter just to the right of the previous one. The red arrow points to the letter that was just placed, in this case an "r". That letter extends beyond the right margin, so we need to move its entire word to the next line.
place When I amNil Do return me When Always Do my positionBecomes whole width atRandom, whole height atRandom. rule tell my successor to 'place'.
I amNil
return me
Always
my positionBecomes whole width atRandom, whole height atRandom. rule tell my successor to 'place'.
positionBecomes
tell
to
If the walk back (blue arrow) gets all the way to the left margin, a single word covers the entire line. Which letter should be moved to the next line? The original clipped letter (red arrow) is the proper letter to move. A single word that covers the entire line is a special case, and we must test for it.
Text Field Specification
Finding the Start of a Word We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line. backToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line. backToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line.
ackToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
first calls
which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
startOfWord travels back along the word to find the first letter. We are looking for a letter that is not white space. If we happen come to the first letter of the text, return it instead. startOfWord considers just one letter. If that letter is not the start of a word, it calls itself again to consider the preceeding letter.
startOfWord
startOfWord
Is a Letter at the Start of a Line? Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
lay out text
reset
Accept
startOfWord travels back along the word to find the first letter. We are looking for a letter that is not white space. If we happen come to the first letter of the text, return it instead. startOfWord considers just one letter. If that letter is not the start of a word, it calls itself again to consider the preceeding letter.
startOfWord
startOfWord
Accept
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
Place each letter just to the right of the previous letter on the current line. Then, look for special cases. If the letter follows a carriage return, move it to the next line. (This is done inside placeIfAfterReturn). The letter has the goal of not being clipped by the right margin. When a letter is not white space and finds that it is being clipped, run the backToWordStart rule. It looks backwards to find the start of the current word, and moves that letter to the next line.
Place
placeIfAfterReturn
backToWordStart
Wrapping the Text to a New Line When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general layout rule. It moves the first letter to the upper left. Then, it the tells the next letter to place itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to place.
When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general
When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general
ayout rule. It moves the first letter to the upper left. Then, it the tells the next letter to place itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to place.
rule. It moves the first letter to the upper left. Then, it the tells the next letter to
itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to
.
isStartOfLine When Always Do return (whole at me) pivotPosition x - inset x <=? "left margin" (whole shape leftAtY (whole at me) pivotPosition y)
Always
return (whole at me) pivotPosition x - inset x <=? "left margin" (whole shape leftAtY (whole at me) pivotPosition y)
at
leftAtY
at
Accept
Finding the Start of a Word We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line. backToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line. backToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line.
ackToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
first calls
which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
Is a Letter at the Start of a Line? Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
Accept
placeIfAfterReturn When my predecessor shape notNil and [my predecessor shape isNewline] Do "start of the next line" my pivotPosition 0 , (my predecessor pivotPosition y + maxHeight + maxDescent + 2). my pivotPosition ((whole shape leftAtY my pivotPosition y) + inset x) , my pivotPosition y. maxDescent := my descent. missingHeight := 0. return true. When Always Do return false.
my predecessor shape notNil and [my predecessor shape isNewline]
and
"start of the next line" my pivotPosition 0 , (my predecessor pivotPosition y + maxHeight + maxDescent + 2). my pivotPosition ((whole shape leftAtY my pivotPosition y) + inset x) , my pivotPosition y. maxDescent := my descent. missingHeight := 0. return true.
pivotPosition
pivotPosition
leftAtY
Always
return false.
Accept
Rules The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the When. If the guard is true, then execute the Do part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses. Extremely Simple Layout Methods Random Layout As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for layout and place. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the
The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the
hen. If the guard is true, then execute the Do part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses.
. If the guard is true, then execute the
part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses.
As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for
As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for
ayout and place. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
and
. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
isClipped When my shape isWhiteSpace Do return false. When Always Do return my right + inset x > (whole shape rightAtY my pivotPosition y)
my shape isWhiteSpace
return false.
Always
return my right + inset x > (whole shape rightAtY my pivotPosition y)
rightAtY
place When I amNil Do return me. When Always Do pred := my predecessor. my pivotPosition pred right + pred pivotOffset x , pred pivotPosition y. When rule placeIfAfterReturn me Do return rule tell my successor to 'place'. When rule isClipped me Do rule tell me to 'backToWordStart'. When (rule isClipped me) not Do rule tell my successor to 'place'.
I amNil
return me.
Always
pred := my predecessor. my pivotPosition pred right + pred pivotOffset x , pred pivotPosition y.
pivotPosition
rule placeIfAfterReturn me
placeIfAfterReturn
return rule tell my successor to 'place'.
tell
to
rule isClipped me
isClipped
rule tell me to 'backToWordStart'.
tell
to
(rule isClipped me) not
isClipped
rule tell my successor to 'place'.
tell
to
Noticing a Carriage Return The rule placeIfAfterReturn actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line. placeIfAfterReturn always returns true or false. This allows it to be used in a guard clause. You can see this in the place rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on to
The rule
The rule
laceIfAfterReturn actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line. placeIfAfterReturn always returns true or false. This allows it to be used in a guard clause. You can see this in the place rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on to
actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line.
always returns true or false. This allows it to be used in a guard clause. You can see this in the
rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on to
Text Field Specification
the next letter. For all other letters, it returns false, which signals the place rule to go further and test whether the current letter is over the right margin. maxHeight and missingHeight are used to move the line down when a tall letter is in the middle of the line. We will hook this up later in the essay.
Accept
How to Break the Line of Text
reset
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
Accept
Text Field Specification
How to Break the Line of Text
To layout the text in the field, place the next letter just to the right of the previous one. The red arrow points to the letter that was just placed, in this case an "r". That letter extends beyond the right margin, so we need to move its entire word to the next line.
Walk back with the blue arrow until we reach the first letter of the word.
Move that letter to the next line. Resume placing letters to the right of the "o", as indicated by the red arrow. Notice that all letters in the word "over" are placed more than once during the layout.
If the walk back (blue arrow) gets all the way to the left margin, a single word covers the entire line. Which letter should be moved to the next line? The original clipped letter (red arrow) is the proper letter to move. A single word that covers the entire line is a special case, and we must test for it.
Wrapping the Text to a New Line When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general layout rule. It moves the first letter to the upper left. Then, it the tells the next letter to place itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to place.
When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general
When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general
ayout rule. It moves the first letter to the upper left. Then, it the tells the next letter to place itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to place.
rule. It moves the first letter to the upper left. Then, it the tells the next letter to
itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to
.
Accept
layout When whole contents isEmpty not Do rule tell whole contents first to 'place'. rule processActions.
whole contents isEmpty not
rule tell whole contents first to 'place'. rule processActions.
tell
to
Text Field Specification
Place each letter just to the right of the previous letter on the current line. Then, look for special cases. If the letter follows a carriage return, move it to the next line. (This is done inside placeIfAfterReturn). The letter has the goal of not being clipped by the right margin. When a letter is not white space and finds that it is being clipped, run the backToWordStart rule. It looks backwards to find the start of the current word, and moves that letter to the next line.
Place
placeIfAfterReturn
backToWordStart
Noticing a Carriage Return The rule placeIfAfterReturn actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line. placeIfAfterReturn always returns true or false. This allows it to be used in a guard clause. You can see this in the place rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on to
The rule
The rule
laceIfAfterReturn actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line. placeIfAfterReturn always returns true or false. This allows it to be used in a guard clause. You can see this in the place rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on to
actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line.
always returns true or false. This allows it to be used in a guard clause. You can see this in the
rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on to
the next letter. For all other letters, it returns false, which signals the place rule to go further and test whether the current letter is over the right margin. maxHeight and missingHeight are used to move the line down when a tall letter is in the middle of the line. We will hook this up later in the essay.
Noticing going beyond the right margin isClipped is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
sClipped is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
All in One Line Now let's redefine place to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the place rule. The line is clipped by the edge of the field.
Now let's redefine
Now let's redefine
lace to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the place rule. The line is clipped by the edge of the field.
to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the
rule. The line is clipped by the edge of the field.
place When I amNil Do return me When my index = 1 Do my position (whole shape leftAtY 0)+4 , 4. return rule tell my successor to 'place'. When Always Do pred := my predecessor. my pivotPosition pred left + pred pivotOffset x + pred width , pred pivotPosition y. rule tell my successor to 'place'.
I amNil
return me
my index = 1
my position (whole shape leftAtY 0)+4 , 4. return rule tell my successor to 'place'.
position
leftAtY
tell
to
Always
pred := my predecessor. my pivotPosition pred left + pred pivotOffset x + pred width , pred pivotPosition y. rule tell my successor to 'place'.
pivotPosition
tell
to
reset
Text Field Specification
Rules The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the When. If the guard is true, then execute the Do part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses. Extremely Simple Layout Methods Random Layout As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for layout and place. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the
The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the
hen. If the guard is true, then execute the Do part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses.
. If the guard is true, then execute the
part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses.
As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for
As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for
ayout and place. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
and
. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
All in One Line Now let's redefine place to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the place rule. The line is clipped by the edge of the field.
Now let's redefine
Now let's redefine
lace to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the place rule. The line is clipped by the edge of the field.
to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the
rule. The line is clipped by the edge of the field.
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
lay out text
reset
lay out text
reset
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
startOfWord When my predecessor isNil Do return me. When my predecessor shape isWhiteSpace Do return me. When Always Do return rule startOfWord my predecessor.
my predecessor isNil
return me.
my predecessor shape isWhiteSpace
return me.
Always
return rule startOfWord my predecessor.
startOfWord
lay out text