Blame mono/EllipseTruncate/ActiveAngleRange.cs

782bf6
using System;
782bf6
782bf6
namespace EllipseTruncate {
782bf6
	public class ActiveAngleRange {
782bf6
		public double width = 0.1;
782bf6
	
782bf6
		public Point point;
782bf6
		public double radius;
782bf6
		public AngleRange.Entry current;
782bf6
		public AngleRange a = new AngleRange();
782bf6
		public AngleRange b = new AngleRange();
782bf6
		
782bf6
		public ActiveAngleRange(Point point, double radius) {
782bf6
			this.point = point;
782bf6
			this.radius = radius;
782bf6
		}
782bf6
782bf6
		public void add() {
782bf6
			a.add(current);
782bf6
			current = new AngleRange.Entry();
782bf6
		}
782bf6
782bf6
		public void xor() {
782bf6
			a.xor(current);
782bf6
			current = new AngleRange.Entry();
782bf6
		}
782bf6
782bf6
		public void subtract() {
782bf6
			a.subtract(current);
782bf6
			current = new AngleRange.Entry();
782bf6
		}
782bf6
		
782bf6
		public void scale(Cairo.Context context, double level = 1.0) {
782bf6
			double k = Math.Pow(1.0 + 1.5*width, level);
782bf6
			context.Scale(k, k);
782bf6
		}
782bf6
		
782bf6
		public void draw(Cairo.Context context, uint a0, uint a1, double level = 0.0) {
782bf6
			if (a0 == a1) return;
782bf6
			
782bf6
			context.Save();
782bf6
			scale(context, level);
782bf6
			context.LineWidth = width;
782bf6
			double aa0 = AngleRange.toDouble(a0);
782bf6
			double aa1 = AngleRange.toDouble(a1);
782bf6
			if (a1 < a0) aa1 += AngleRange.period;
782bf6
			if (aa1 < aa0) return;
782bf6
			
782bf6
			context.Arc(0.0, 0.0, 1.0, aa0, aa1);
782bf6
			context.Stroke();
782bf6
			context.Restore();
782bf6
		}
782bf6
		
782bf6
		public void draw(Cairo.Context context, AngleRange r, double level = 0.0) {
782bf6
			context.Save();
782bf6
			scale(context, level);
782bf6
			if (r.isEmpty()) {
782bf6
				context.LineWidth = 0.25*width;
782bf6
				context.SetDash(new double[] { 0.1, 0.02 }, 0.0);
782bf6
				context.Arc(0.0, 0.0, 1.0, 0.0, 2.0*Math.PI);
782bf6
				context.Stroke();
782bf6
			} else
782bf6
			if (r.isFull()) {
782bf6
				context.LineWidth = width;
782bf6
				context.Arc(0.0, 0.0, 1.0, 0.0, 2.0*Math.PI);
782bf6
				context.Stroke();
782bf6
				context.LineWidth = 0.25*width;
782bf6
				context.SetDash(new double[] { 0.1, 0.03 }, 0.0);
782bf6
				context.Arc(0.0, 0.0, 1.0, 0.0, 2.0*Math.PI);
782bf6
				context.Stroke();
782bf6
			} else {
782bf6
				context.LineWidth = 0.25*width;
782bf6
				context.Arc(0.0, 0.0, 1.0, 0.0, 2.0*Math.PI);
782bf6
				context.Stroke();
782bf6
				bool f = r.flip;
782bf6
				uint prev = r.angles[r.angles.Count - 1];
782bf6
				foreach(uint a in r.angles) {
782bf6
					if (f) draw(context, prev, a);
782bf6
					prev = a; f = !f;
782bf6
				}
782bf6
			}
782bf6
782bf6
			if (!r.check()) {
782bf6
				context.LineWidth = width;
782bf6
				context.SetDash(new double[] { 0.1, 0.02 }, 0.0);
782bf6
				context.Arc(0.0, 0.0, 1.0, 0.0, 2.0*Math.PI);
782bf6
				context.Stroke();
782bf6
			}
782bf6
782bf6
			context.Restore();
782bf6
		}
782bf6
		
782bf6
		public void draw(Cairo.Context context) {
782bf6
			context.Save();
782bf6
			context.Translate(point.x, point.y);
782bf6
			context.Scale(radius, radius);
782bf6
			
782bf6
			AngleRange x = new AngleRange();
782bf6
782bf6
			// back circle
782bf6
			context.SetSourceRGBA(1.0, 0.0, 0.0, 0.1);
782bf6
			context.Arc(0.0, 0.0, 1.0, 0.0, 2.0*Math.PI);
782bf6
			context.Fill();
782bf6
782bf6
			// a
782bf6
			context.SetSourceRGBA(0.0, 0.0, 0.0, 0.5);
782bf6
			draw(context, a);
782bf6
782bf6
			// b
782bf6
			context.SetSourceRGBA(0.0, 0.0, 1.0, 0.5);
782bf6
			draw(context, b, 1.0);
782bf6
782bf6
			// current
782bf6
			context.SetSourceRGBA(0.0, 0.0, 1.0, 0.5);
782bf6
			if (!current.isEmpty())
782bf6
				draw(context, current.a0, current.a1);
782bf6
782bf6
			// !a
782bf6
			context.SetSourceRGBA(0.5, 0.5, 0.5, 0.5);
782bf6
			x.set(a); x.invert();	
782bf6
			draw(context, x, -1.0);
782bf6
			
782bf6
			scale(context);
782bf6
			
782bf6
			// a xor b
782bf6
			scale(context);
782bf6
			context.SetSourceRGBA(0.0, 0.5, 0.0, 0.5);
782bf6
			x.set(a);
782bf6
			x.xor(b);
782bf6
			draw(context, x);
782bf6
782bf6
			// a | b
782bf6
			scale(context);
782bf6
			context.SetSourceRGBA(0.0, 0.5, 0.0, 0.5);
782bf6
			x.set(a);
782bf6
			x.add(b);
782bf6
			draw(context, x);
782bf6
			
782bf6
			// a & ~b
782bf6
			scale(context);
782bf6
			context.SetSourceRGBA(0.0, 0.5, 0.0, 0.5);
782bf6
			x.set(a);
782bf6
			x.subtract(b);
782bf6
			draw(context, x);
782bf6
782bf6
			// a & b
782bf6
			scale(context);
782bf6
			context.SetSourceRGBA(0.0, 0.5, 0.0, 0.5);
782bf6
			x.set(a);
782bf6
			x.intersect(b);
782bf6
			draw(context, x);
782bf6
			
782bf6
			context.Restore();
782bf6
		}
782bf6
	}
782bf6
}
782bf6