Since \badness
is overwritten at each line break, the only way to keep track of line badness is to let TeX
format a paragraph and then imitating it and reformat it manually line by line keeping track of what we're interested in.
This kind of decomposition-recomposition is not particularly hard to do, the only annoying part being restoring exact vertical spacing (in fact I still haven't got it quite right). A few questions already show the technique, see putting a box around each line of text in a paragraph and the linked ones.
But I won't bore you with some straightforward code cleanup from another answer. It seems to me that it would be most interesting (= fun for me) to automate the process you are doing by trial and error, instead of just facilitating it.
I wrote a macro that takes a paragraph and a line width range. Exploring it with a given step, it searches for the one minimizing the maximum badness present in the paragraph. Then it sets the paragraph at the optimal width, rescaled to fit the original one.
Here is the result:
On the left there's the ratio of original and optimal line width, i.e. the scale factor. On the right there's the badness of each line; the maximum is bold.
This is a bit more than what you asked for, but to do it I had to find the badness of each line (and keep track of the maximum). This is exactly what you have to do to find wether a paragraph contains an overfull line (by checking the maximum or maybe more elegantly breaking the recursion if one is found). The basic technique is there.
However I think that it's a bit more convenient to have something to search for the optimal width and output it instead of you doing it manually.
Also, there's another answer you might be interested in here.
Here is the code:
% Unessential but I don't want to
% reimplement \resizebox from scratch.
\input miniltx
\input graphics.sty
% internal variables
\newbox\linebox
\newif\ifmeasuring
\newif\ifverbose
% line width variables:
\newdimen\lwMIN % range minimum
\newdimen\lwMAX % range maximum
\newdimen\lwINC % increase step
\newdimen\lwCUR % currently evaluated
\newdimen\lwOPT % optimum
% line badness variables:
\newcount\lbCUR % current line badness
\newcount\lbMAX % max of the paragraph
\newcount\lbOPT % optimum
% \fit formats the following paragraph
% finding the line width in the given
% range by minimizing the maximum line
% badness and rescaling in to fit.
\def\fit#1#2#3#4\par{
% read parameters
\lwMIN=#1
\lwMAX=#2
\lwINC=#3
% find optimum
\measuringtrue
\lwCUR=\lwMIN
\lbOPT=1000000
{\find#4\par}
% format optimum
\verbosetrue
\measuringfalse
\lwCUR=\hsize
{\hsize=\lwOPT\global\setbox0=\vbox{#4\par\eat}}
% place optimum
\noindent\resizebox\hsize!%
{\ifverbose\llap{\bf$\the\hsize\over\the\lwOPT$~}\fi\box0}\par
}
% \find searches line widths in the
% given range to find the optimum to
% format the passed paragraph
\def\find#1\par{
% prepare measure at current line width
\hsize=\lwCUR
\lbMAX=0
% measure paragraph's maximum badness
\setbox0=\vbox{#1\par\eat}
% if in valid range
\ifnum\lwCUR<\lwMAX
% update optima
\ifnum\lbMAX<\lbOPT
\global\lbOPT=\lbMAX
\global\lwOPT=\lwCUR\fi
% evaluate next line width
\advance\lwCUR\lwINC
\find#1\par\fi
}
% \eat eats lines of the last paragraph
% either measuring its maximum badness
% or re-setting it with annotations.
\def\eat{{
% eat line and measure its badness
\setbox\linebox=\lastbox
\setbox0=\hbox to \hsize{\unhcopy\linebox}
\lbCUR=\badness
% if measuring update the maximum badness of the paragraph
\ifmeasuring\ifnum\lbCUR>\lbMAX\global\lbMAX=\lbCUR\fi\fi
% unless paragraph is over
\ifvoid\linebox\else
% nest call and process preceeding line
\unskip\unpenalty\eat
% unless measuring
\ifmeasuring\else
% set current line
\ifhmode\break\fi\noindent\box\linebox
% if verbose annotate badnesses
\ifverbose\rlap{~$\ifnum\lbCUR=\lbOPT\bf\fi\the\lbCUR$}\fi\fi\fi
}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input zapf\par\fit{200pt}{600pt}{.1pt}\input zapf\par
\input zapf\par\fit{250pt}{350pt}{10pt}\input zapf\par
\input zapf\par\fit{600pt}{800pt}{50pt}\input zapf\par
\input zapf\par
\bye
\lastbox
,\unskip
,\unpenalty
) and re-typeset each line into a box of width\hsize
to test their badness? You're actually more than half-way to an answer to the question «Obtain \badness or glue adjustment for each line». (I'd say it's more natural to initialize\maxbad
globally since later assignments are global.)\hss
in\eatlines
? It is not there in\printlines
.\begin{minipage}[t]{55pt} \mbox{} \trypar\hyphenpenalty=-500\looseness=1
.\hfuzz=0pt \overfullrule=7pt
would give a visual clue for overfull lines in the document. 2. The ctan.org/pkg/adjustbox package might be helpful to solve the original problem (fit some math to some width).