1. I recently discovered the Gimp and decided that it's the greatest
   thing since sliced bread and just what I need ...

2. ... except that it cannot draw thin lines and curves that look
   nice. I'm not the first to discover this, see e.g. bug #69773,

3. Last August there was a thread about ways to fix the problem:

4. That thread seemed to end up with a rough consensus that a solution
   that worked for thin lines would be a Good Thing, and that it might
   be acceptable to change the basic line-drawing engine to be more
   DDA/bresenham-ish to make that work,

5. However, nothing concrete seems to have come of that. At least the
   word "bresenham" has not been uttered on the list ever since, and
   thin lines are still ugly in 1.3.7 (but I may be wrong. If so,
   please tell me), and

6. I think I have a workable idea of what needs to be done (see
   below), and after having hunted down a rounding bug related to
   line drawing, I even feel competent to make some rough guesses
   about where in the source code it should be done,

I hereby offer my programming skills to the task.

[That being, if you want them. I'm not quite sure where on the
cathedral-bazaar scale the Gimp core lies, but the guy I met on
comp.graphics.app.gimp (hi, Dave!) seemed rather eager to send me
here so I don't expect to have my head bitten off.]

In greater detail: I understand that the Gimp draws lines by stamping
the brush image at equidistant places along the line. The problem with
thin lines is that those equidistant places are computed in floating
point without any particular attention to pixel boundaries. This gives
ugly lines when the brush is only one or a few pixels across, no
matter (but in different ways) whether the pixel stamps are
anti-aliased or not.

As long as we're only drawing straight lines with an 1x1 brush and
spacing 1.0, the solution is clear: just adjust the positions of the
brush centers along the abstract line such that they all have
integral-plus-one-half x coordinates if the slope is horizontalish,
and integral-plus-one-half y coordinates if the slope is verticalish.

The challenge is to let this scale to (a) larger spacing, bigger
brushes, and (b) stroking of cubic spline paths.

Regarding (b), the "obvious" idea is to divide the spline into
segments according to the octant of tangent. However, it becomes
difficult to find a simple way to make two segments with different
orientations always meet seamlessly in case of a 1x1 brush with
antialiasing. Instead I propose another solution: compute all points
along the spline where *either* the x coordinate *or* the y coordinate
has fractional part equal to 1/2 - then select a suitable subset of
these points to draw, according to the brush spacing (see below).

These "extra" brush positions will be invisible if all points are
painted with a 1x1 brush - if the paint from neighbouring brush
positions is combined by "maximum" rather than "addition", the "extra"
brush stamps will always have lower intensity than their "ordinary"
neighbours combined. This holds for the pencil as well as for the
brush, as long as the spline is locally approximated by a line. But
the admission of "extra" positions means that there will be no
discontinuity when the spline's tangent passes from one octant to

Brush spacing now becomes a matter of choosing among the candidate
points (defined as those where one or both coordinates is n+1/2)
such that the (euclidean) distance between successive actiual painting
operations is at least <spacing>.

So, do you think this is worth wasting time on? If so, what is the
protocol for "outsider"s contributing to the Gimp - does one just post
patches to this list, or must I find a sponsor with commit priveleges,
or what?

I also have a design for a "stroke selection" operation that creates
nice thin AA outlines if the selection was made with AA tools, but
that would not be as easy to integrate with the Gimp's user interface

Henning Makholm                                   "Monsieur, vous Ítes fou."

Gimp-developer mailing list

Reply via email to