Re: Rounded corners




Am 29.05.2008 05:37, Don Blaheta schrieb:
I've been playing around with lib/diagdkrenderer.c to try and work on bug #534275. I noticed the changes made in the recent SVN update, which partially solve the problem, but there are a few problems still.

2008-05-25  Hans Breuer  <hans breuer org>

        Attempts to fix bug #534275
        * lib/diagdkrenderer.c(draw_fill_rounded_rect) : attempt to make
        arc drawing for radius<line_width less backend specific.
        * objects/standard/box.c objects/standard/polyline.c
          objects/standard/zigzagline.c :
        set LINEJOIN_ROUND when rendering "rounded" (with radius>0)


What I was trying to say here was: arc drawing (rounded somethings) are highly backend specific for radius near or smaller than half of the linewidth. Your are right that the definition needs to come first, but my current impression is that you may be requesting too much.

In my implmentation I tried to work around (and only partitially succeeded) the lack of backend capabilities. But if this is really to be solved it is not only a matter of the GdkRenderer but preferably also of all other renderers.

The biggest, I think, is that "corner radius" is being used to mean two
different things: the radius of rounding for a rounded rectangle, and
the radius of rounding for the cap of a regular rectangle.
If I understand the terminology correctly 'caps' are only at the end of lines, see e.g.: http://library.gnome.org/devel/gdk/stable/gdk-Graphics-Contexts.html#GdkCapStyle ; but we need 'joins' here because we are talking about the radius between line segments, see: http://library.gnome.org/devel/gdk/stable/gdk-Graphics-Contexts.html#GdkJoinStyle

The former
it is reasonable to measure from the control points (as it is), although
measuring from the inside or outside edge would also be reasonable; the
latter really must be measured from the outside edge.
The latter just was undefined behaviour and kind of it still is. My attempt for rectangles was piecewise approximation with longer lines and smaller and thinner arcs to fill the corners. Maybe it would be better to adapt the definition to:
  radius==0 : JOIN_MITER
  radius>0 && <line_width/2 : JOIN_ROUND
  radius>line_width/2 : draw arcs

The current workaround is to say that if the given radius is less than
half the width of the line, treat it as a cap and measure from the
outside edge, and otherwise measure from the control points.  I had to
go into the code to figure out what was going on there, because it
seemed buggy when I was just playing with it: if you compare two boxes
with line width 4, one with corner radius 2 and one with radius 1.99,
they look very different!  I don't think this will work.  (It's also not
mirrored in the zigzagline or polylines.)

Yes, distributing something which (maybe) can't work to other implementations did not look feasible to me. So if it is not going to work for rectangles how should it work for the other rounded lines?

I see three possible solutions:

* Treat rounded rectangles as different objects from regular boxes.  A
  rounded rectangle has a corner radius that works as the box corner
  radius does now; a regular box has a "cap radius" that measures from
  the outside edge of the line.  If the cap radius is zero, the cap is a
  square cap.  The cap radius cannot be larger than the line width.
  A rounded rectangle with corner radius zero would look like a regular
  box with cap radius of half the linewidth.  Polylines and Zigzaglines
  would be made to match the regular box behaviour; as it stands they
  already can't have a corner radius that rounds more than just the
  corner cap.

I still don't think there is a good implmentation to do *joins* smaller than half the line_width. Also this would mean a further explosion of options, i.e. where for all the boxes drawn woud be made the decision of "rounded rectangles" vs. "regular boxes"?

* Treat all rectangles as the same, but always measure the corner radius
  from the outside edge of the line.  This is probably ok, but it does
  mean that the curve of the corner changes when the line width does.
  Polylines and zigzaglines are modified to match.

Looks most similar to what I came up with above. But it seems quite difficult to make this work for all the renderers.

* Revert the behaviour of rounded rectangles to always measure the
  corner radius from the control points, but add a boolean flag to boxes
  that chooses rounded vs square cap; it would be greyed out if the
corner radius is other than zero.
"Greying out" some parameter depending on some other parameter is not going to be easy with the way Dia handles it's properties. If you would want to modify multiple objects (in a group) it even can't work by concept.

"Rounded" would make a radius of
  exactly half the linewidth.  Polylines and zigzaglines get the
  checkbox as well instead of a corner radius option.

The almost independent parameter which could be given to all the renderers is the line join. Maybe we should allow the user to set it, instead of hardcoding the behaviour for radius>=0 && radius<line_width?

How do Visio and other such programs handle any of this?

I Looked at some other renderers Dia has - namely antialised vias cairo and wmf and the implmentation looks like the radius is applied at the control rectangle. For radius 0 it gives sharp edges, for 0.1 it has an outer radius of almost half of the line width.

Now I think the GdkRenderer should be fixed in that direction.

Regards,
        Hans

-------- Hans "at" Breuer "dot" Org -----------
Tell me what you need, and I'll tell you how to
get along without it.                -- Dilbert



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]