[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Fix: NSBezierPath, appendBezierPathWithArcWithCenter (2)
From: |
Nicola Pero |
Subject: |
Re: Fix: NSBezierPath, appendBezierPathWithArcWithCenter (2) |
Date: |
Wed, 7 Mar 2001 04:59:19 +0100 (CET) |
Hi Georg,
> > startAngle = 0
> > endAngle = -450
> > clockwise
> >
> > it wouldn't work... <it would draw a full circumference rather than simply
> > from -90 to 0>
>
> Thats exactly what it does, and I think its the correct behavior.
Ok - so we don't agree on what the API is supposed to do. :-)
To add to the confusion, the macos-x doc for NSBezier path says that the
`clockwise' argument determines whether angles are measured clockwise or
counterclockwise, while postscript operators and common sense push us to
interpret that argument as whether the arc is to be drawn clockwise or
counterclockwise (which is a pretty different concept).
I think it's probably a bug in the doc and I'd really tend to read the API
in the postscript way, but I can't test the behaviour on macos-x. Do you
agree at least on this point - interpreting it in the postscript way ?
Can anyone test it ? <we are talking about
[NSBezierPath
-appendBezierPathWithArcWithCenter:radius:startAngle:endAngle:clockwise:]>
If we agree that we had to interpret the arguments to NSBezierPath in the
same way as the arguments to the postscript operators `arc' and `arcn',
then we can use the reference doc for those to determine how it should
work.
So - I looked at the postscript reference for the `arc' and `arcn'
operators.
Other doc is vague, but the postscript reference prescribes exactly the
algorithm to use for the angles in arc -
`If angle_2 [end angle] is less than angle_1 [start angle], it is
increased by multiples of 360 until it becomes greater than or equal to
angle_1. No other adjustments are made to the two angles. In particular,
the angle subtended by the arc is not reduced modulo 360; if the
difference angle_1 - angle_2 exceeds 360, the resulting path will trace
portions of the circle more than once.'
I won't bother you with the explanation of why I don't like this
prescription at all (but eg :-), try drawing an arc between angles 0 and
-{a little number} (such as -0.1) using arc - the result will be either a
full circle or nothing depending on how little the number is - on my
system -0.001 generates a full circle, while -0.0001 generates nothing -
it is the hardware which determines whether your arc command draws a full
circle or nothing...)
Anyway - the prescription works perfectly fine for angles between 0 and
360 - it's the standard documented postscript prescription so I agree with
using it.
Here is a patch implementing this prescription -
Index: NSBezierPath.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/gui/Source/NSBezierPath.m,v
retrieving revision 1.8
diff -u -r1.8 NSBezierPath.m
--- NSBezierPath.m 2001/03/01 01:47:32 1.8
+++ NSBezierPath.m 2001/03/07 01:22:37
@@ -833,7 +833,7 @@
[self appendBezierPath: [isa bezierPathWithOvalInRect: aRect]];
}
-/* startAngle and endAngle are in degrees, counterclockwise, from the
+/* startAngle and endAngle are in degrees, counterclockwise, from the
x axis */
- (void) appendBezierPathWithArcWithCenter: (NSPoint)center
radius: (float)radius
@@ -844,16 +844,37 @@
float startAngle_rad, endAngle_rad, diff;
NSPoint p0, p1, p2, p3;
- while (startAngle < 0)
- startAngle = startAngle + 360;
- while (startAngle > 360)
- startAngle = startAngle - 360;
-
- while (endAngle < 0)
- endAngle = endAngle + 360;
- while (endAngle > 360)
- endAngle = endAngle - 360;
+ /* We use the Postscript prescription for managing the angles and
+ drawing the arc. See the documentation for `arc' and `arcn' in
+ the Postscript Reference. */
+ if (clockwise)
+ {
+ /* This modification of the angles is the postscript
+ prescription. */
+ while (startAngle < endAngle)
+ endAngle -= 360;
+
+ /* This is used when we draw a clockwise quarter of
+ circumference. By adding diff at the starting angle of the
+ quarter, we get the ending angle. diff is negative because
+ we draw clockwise. */
+ diff = - PI / 2;
+ }
+ else
+ {
+ /* This modification of the angles is the postscript
+ prescription. */
+ while (endAngle < startAngle)
+ endAngle += 360;
+
+ /* This is used when we draw a counterclockwise quarter of
+ circumference. By adding diff at the starting angle of the
+ quarter, we get the ending angle. diff is positive because
+ we draw counterclockwise. */
+ diff = PI / 2;
+ }
+
/* Convert the angles to radians */
startAngle_rad = PI * startAngle / 180;
endAngle_rad = PI * endAngle / 180;
@@ -862,23 +883,6 @@
p0 = NSMakePoint (center.x + radius * cos (startAngle_rad),
center.y + radius * sin (startAngle_rad));
[self moveToPoint: p0];
-
- if (clockwise)
- {
- diff = -PI / 2;
- if (startAngle_rad < endAngle_rad)
- {
- startAngle_rad += 2 * PI;
- }
- }
- else
- {
- diff = PI / 2;
- if (startAngle_rad > endAngle_rad)
- {
- startAngle_rad -= 2 * PI;
- }
- }
while ((clockwise) ? (startAngle_rad > endAngle_rad)
: (startAngle_rad < endAngle_rad))
Yes - it is your patch :-) - except for my verbose comments and for the
fact that - since we are following the postscript doc, we must not modify
startAngle at the beginning - so I removed the code which did it.
Does this patch look right to you ?
Basically you convinced me to use the postscript way of doing it, and your
patch - with a little fix - implements it (I hadn't realized that was what
you wanted to do!), so I agree with using it rather than what I sent to
you (which implemented my own tentative guess of what the API could mean).
If it's Ok, we can apply to CVS.
> If the current point is not the start point of the arc, PostScript draws a
> line from the current position to the start of the arc.
> To get this behavior in GNUstep, appendBezierPathWithArcWithCenter just has
> to
> perform a lineto instead of a moveto to the start position of the arc (if a
> current point is defined).
Yes - that's what the backend should do in response to arc commands; but I
think the macos-x doc for NSBezierPath says that we should not draw the
line in NSBezierPath. I need to look at it - but if the backend is using
NSBezierPath to draw the arc, then what we need to do is adding the line
in the backend before it draws the arc using NSBezierPath.