[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Groff] Formatting algorithm
From: |
Peter Schaffter |
Subject: |
[Groff] Formatting algorithm |
Date: |
Mon, 31 Mar 2014 19:44:07 -0400 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
Here's the bare bones version of the algorithm I was thinking of
when I proposed improving line formatting by getting groff to
shoulder the burden for some of the work we do manually. It's
written out in brute-force pseudo-code; should be pretty clear.
The aim is not to find optimal breaks in Knuthian fashion, but to
improve the uniformity of grey from line to line using a greedy
algorithm. Key features are that letterspacing and wordspacing are
orthogonal, and that NextWord can be read during optimization.
The chief reason for opening discussion about this is because I
don't want implementation of KP carved in stone in the mission
statement unless we're fully committed to it. Our goal is to
improve paragraph formatting; if it looks like there may be more
than one way to make it happen, we should be considering the
possibilities now.
# Assumptions
# ===========
# WordSpace:
# - can be shrunk
# - is independent of letterspacing
# - is stretchable when Line is printed
# Line:
# - letterspaced Width(Line) can be calculated
# NextWord:
# - can be read from a buffer
#
SpaceWidth(Opt) := WordSpace
SpaceWidth(Min) := SpaceWidth(Opt) - n
Unit(LetterSpace) := PointSize / 100 # 100 is arbitrary
LetterSpace(Max) := LetterSpace + Units(LetterSpace)
LetterSpace(Min) := LetterSpace - Units(LetterSpace)
Width(Space) := SpaceWidth(Opt)
LetterSpace := 0
SpaceLeft := LineLength
for each Word in Text {
# Line is short by Width(Space); apply positive letterspacing
# Width(Space) is arbitrary; the value could be larger or smaller
if (SpaceLeft > 0) and (SpaceLeft <= Width(Space)) {
until (SpaceLeft = 0) or (LetterSpace = LetterSpace(Max)) {
LetterSpace := LetterSpace + Unit(LetterSpace)
letterspace Line by LetterSpace
SpaceLeft := LineLength - Width(Line)
}
insert breakpoint before Word
SpaceLeft := LineLength - (Width(Word) + Width(Space))
}
# Line is long by Width(Space); apply negative letterspacing
if (SpaceLeft < 0) and (SpaceLeft <= -(Width(Space)) {
until (SpaceLeft = 0) or (LetterSpace = LetterSpace(Min)) {
LetterSpace := LetterSpace - Unit(LetterSpace)
letterspace Line by LetterSpace
SpaceLeft := LineLength - Width(Line)
}
insert breakpoint before Word
SpaceLeft := LineLength - (Width(Word) + Width(Space))
}
# Word exceeds LineLength
if Width(Word) > SpaceLeft {
Num(Spaces) := Num(Spaces) -1 # remove discardable space
Width(Space) := SpaceWidth(Min)
WordSpace := Width(Space)
SpaceLeft := Num(Spaces) * Width(Space)
if HyphenateWord {
for each Syllable in Word {
if (Width(Syllable) + Width(Hyphen)) > SpaceLeft {
insert breakpoint before Syllable
}
else {
add Syllable to Line
SpaceLeft := SpaceLeft - (Width(Syllable) + Width(Hyphen))
}
}
}
else {
read NextWord
if Width(NextWord) > SpaceLeft {
if HyphenateWord {
for each Syllable in Word {
if (Width(Syllable) + Width(Hyphen)) > SpaceLeft {
insert breakpoint before Syllable
}
else {
add Syllable to Line
SpaceLeft := SpaceLeft - (Width(Syllable) + Width(Hyphen))
}
}
}
}
else {
insert breakpoint before Word
SpaceLeft := LineLength - (Width(Word) + Width(Space))
}
}
# Bring wordspace closer to optimum by negative track kerning
# down to LetterSpace(Min)
if (SpaceLeft / Num(Spaces)) < SpaceWidth(Opt) {
until (SpaceLeft = 0) or (LetterSpacing = LetterSpace(Min)) {
LetterSpace := LetterSpace - Unit(LetterSpace)
letterspace Line by LetterSpace
SpaceLeft := LineLength - Width(Line)
}
}
# Bring wordspace closer to optimum by positive track kerning
# up to LetterSpace(Max)
if (SpaceLeft / Num(Spaces)) > SpaceWidth(Opt) {
until (SpaceLeft = 0) or (LetterSpacing = LetterSpace(Max) {
LetterSpace := LetterSpace + Unit(LetterSpace)
letterspace Line by LetterSpace
SpaceLeft := LineLength - Width(Line)
}
}
WordSpace := SpaceWidth(Min) # WordSpace is stretchable
print Line
Num(Spaces) := 0
LetterSpace := 0
Width(Space) := SpaceWidth(Opt)
WordSpace := Width(Space)
}
else {
add Word to Line
SpaceLeft := LineLength - (Width(Word) + Width(Space))
Num(Spaces) := Num(Spaces) + 1
}
}
--
Peter Schaffter
http://www.schaffter.ca
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Groff] Formatting algorithm,
Peter Schaffter <=