From b82ef41253bca747cae1e8dabc3f5a282c6d8c1b Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Feb 08 2018 12:54:02 +0000 Subject: assistance: gtk --- diff --git a/mono/Assistance/ActivePoint.cs b/mono/Assistance/ActivePoint.cs index 4ab7bac..78e43b6 100644 --- a/mono/Assistance/ActivePoint.cs +++ b/mono/Assistance/ActivePoint.cs @@ -1,7 +1,6 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; +using Assistance.Drawing; namespace Assistance { public class ActivePoint { @@ -23,10 +22,10 @@ namespace Assistance { public static readonly double radius = 10.0; public static readonly double crossSize = 1.2*radius; - public static readonly Pen pen = Pens.Gray; - public static readonly Brush brush = Brushes.LightGray; - public static readonly Pen penActive = Pens.Blue; - public static readonly Brush brushActive = Brushes.LightBlue; + public static readonly Pen pen = new Pen("Gray"); + public static readonly Brush brush = new Brush("Light Gray"); + public static readonly Pen penActive = new Pen("Blue"); + public static readonly Brush brushActive = new Brush("Light Blue"); public readonly Document document; public readonly Owner owner; @@ -62,31 +61,46 @@ namespace Assistance { return active ? brushActive : brush; } - private void drawCircle(Graphics g, bool active) { - g.DrawEllipse(getPen(active), (float)(position.x - radius), (float)(position.y - radius), (float)(2.0*radius), (float)(2.0*radius)); + private void drawCircle(Cairo.Context context, bool active) { + context.Save(); + getPen(active).apply(context); + context.Arc(position.x, position.y, radius, 0.0, 2.0*Math.PI); + context.Stroke(); + context.Restore(); } - private void fillCircle(Graphics g, bool active) { - g.FillEllipse(getBrush(active), (float)(position.x - radius), (float)(position.y - radius), (float)(2.0*radius), (float)(2.0*radius)); + private void fillCircle(Cairo.Context context, bool active) { + context.Save(); + getBrush(active).apply(context); + context.Arc(position.x, position.y, radius, 0.0, 2.0*Math.PI); + context.Fill(); + context.Restore(); } - private void drawCross(Graphics g, bool active) { - g.DrawLine(getPen(active), (float)(position.x - crossSize), (float)position.y, (float)(position.x + crossSize), (float)position.y); - g.DrawLine(getPen(active), (float)position.x, (float)(position.y - crossSize), (float)position.x, (float)(position.y + crossSize)); + private void drawCross(Cairo.Context context, bool active) { + context.Save(); + getPen(active).apply(context); + context.MoveTo(position.x - crossSize, position.y); + context.LineTo(position.x + crossSize, position.y); + context.Stroke(); + context.MoveTo(position.x, position.y - crossSize); + context.LineTo(position.x, position.y + crossSize); + context.Stroke(); + context.Restore(); } - public void draw(Graphics g, bool active = false) { + public void draw(Cairo.Context context, bool active = false) { switch(type) { case Type.Circle: - drawCircle(g, active); + drawCircle(context, active); break; case Type.CircleFill: - fillCircle(g, active); - drawCircle(g, active); + fillCircle(context, active); + drawCircle(context, active); break; case Type.CircleCross: - drawCircle(g, active); - drawCross(g, active); + drawCircle(context, active); + drawCross(context, active); break; } } diff --git a/mono/Assistance/Assistance.csproj b/mono/Assistance/Assistance.csproj index a783b76..f036d14 100644 --- a/mono/Assistance/Assistance.csproj +++ b/mono/Assistance/Assistance.csproj @@ -54,11 +54,28 @@ + + - - + + False + glib-sharp-2.0 + + + False + gtk-sharp-2.0 + + + False + gtk-sharp-2.0 + + + + False + gtk-sharp-2.0 + \ No newline at end of file diff --git a/mono/Assistance/Assistant.cs b/mono/Assistance/Assistant.cs index 5a1829e..19d7123 100644 --- a/mono/Assistance/Assistant.cs +++ b/mono/Assistance/Assistant.cs @@ -1,13 +1,11 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; namespace Assistance { public class Assistant: ActivePoint.Owner { public static readonly double maxLen = 1000.0; //public static readonly int gridPointsCount = 100; - public static readonly Pen pen = Pens.Gray; + public static readonly Drawing.Pen pen = new Drawing.Pen("gray"); public Assistant(Document document): base(document) { document.assistants.Add(this); @@ -31,7 +29,7 @@ namespace Assistance { // return maxLen + l; //} - public virtual void draw(Graphics g) { } + public virtual void draw(Cairo.Context context) { } public virtual void getGuidelines(List outGuidelines, Point target) { } } diff --git a/mono/Assistance/AssistantGrid.cs b/mono/Assistance/AssistantGrid.cs index 40d4618..db26c0f 100644 --- a/mono/Assistance/AssistantGrid.cs +++ b/mono/Assistance/AssistantGrid.cs @@ -8,13 +8,13 @@ namespace Assistance { this.center = new ActivePoint(this, ActivePoint.Type.CircleCross, center); } - public override void draw(System.Drawing.Graphics g) { + public override void draw(Cairo.Context context) { /* foreach(Assistant assistant in canvas.assistants) foreach(Point p in assistant.getGridPoints(center.position)) foreach(Assistant a in canvas.assistants) if (a != assistant) - a.drawGuidlines(g, p); + a.drawGuidlines(context, p); */ } } diff --git a/mono/Assistance/AssistantVanishingPoint.cs b/mono/Assistance/AssistantVanishingPoint.cs index 42893fc..5f32363 100644 --- a/mono/Assistance/AssistantVanishingPoint.cs +++ b/mono/Assistance/AssistantVanishingPoint.cs @@ -1,6 +1,4 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; namespace Assistance { @@ -107,11 +105,19 @@ namespace Assistance { } */ - public override void draw(System.Drawing.Graphics g) { - g.DrawLine(pen, center.position.toFloat(), a0.position.toFloat()); - g.DrawLine(pen, center.position.toFloat(), a1.position.toFloat()); - g.DrawLine(pen, center.position.toFloat(), b0.position.toFloat()); - g.DrawLine(pen, center.position.toFloat(), b1.position.toFloat()); + public override void draw(Cairo.Context context) { + context.Save(); + pen.apply(context); + context.MoveTo(center.position.x, center.position.y); + context.LineTo(a0.position.x, a0.position.y); + context.MoveTo(center.position.x, center.position.y); + context.LineTo(a1.position.x, a1.position.y); + context.MoveTo(center.position.x, center.position.y); + context.LineTo(b0.position.x, b0.position.y); + context.MoveTo(center.position.x, center.position.y); + context.LineTo(b1.position.x, b1.position.y); + context.Stroke(); + context.Restore(); } public override void getGuidelines(List outGuidelines, Point target) { diff --git a/mono/Assistance/Canvas.cs b/mono/Assistance/Canvas.cs index ca131fe..9ee910d 100644 --- a/mono/Assistance/Canvas.cs +++ b/mono/Assistance/Canvas.cs @@ -1,6 +1,4 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; namespace Assistance { @@ -8,50 +6,68 @@ namespace Assistance { public static readonly int initialSize = 100; public static readonly double incrementScale = 1.2; - private System.Drawing.Point offset = new System.Drawing.Point(-initialSize/2, -initialSize/2); - private Bitmap bitmap = new Bitmap(initialSize, initialSize); + private int offsetX = -initialSize/2; + private int offsetY = -initialSize/2; + private Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, initialSize, initialSize); - public void draw(Graphics g) { - g.DrawImageUnscaled(bitmap, offset); + public void draw(Cairo.Context context) { + context.Save(); + context.Translate(offsetX, offsetY); + context.SetSource(surface); + context.Paint(); + context.Restore(); } public void expand(Rectangle rect) { - System.Drawing.Point lt = offset; - System.Drawing.Point rb = lt + bitmap.Size; - System.Drawing.Rectangle recti = rect.toInt(); + int l = offsetX; + int t = offsetY; + int r = l + surface.Width; + int b = t + surface.Height; + + int rl = (int)Math.Floor(rect.x0); + int rt = (int)Math.Floor(rect.y0); + int rr = Math.Max(rl, (int)Math.Ceiling(rect.x1)); + int rb = Math.Max(rt, (int)Math.Ceiling(rect.y1)); - int incX = (int)Math.Ceiling(bitmap.Width*incrementScale); - int incY = (int)Math.Ceiling(bitmap.Height*incrementScale); + int incX = (int)Math.Ceiling(surface.Width*incrementScale); + int incY = (int)Math.Ceiling(surface.Height*incrementScale); - if (recti.Left < lt.X) lt.X = recti.Left - incX; - if (recti.Top < lt.Y) lt.Y = recti.Top - incY; - if (recti.Right > rb.X) rb.X = recti.Right + incX; - if (recti.Bottom > rb.Y) rb.Y = recti.Bottom + incY; + if (rl < l) l = rl - incX; + if (rt < t) t = rt - incY; + if (rr > r) r = rr + incX; + if (rb > b) b = rb + incY; - Size size = new Size(rb.X - lt.X, rb.Y - lt.Y); - if (lt != offset || size != bitmap.Size) { - Bitmap newBitmap = new Bitmap(size.Width, size.Height); - Graphics g = Graphics.FromImage(newBitmap); - g.DrawImageUnscaled(bitmap, new System.Drawing.Point(offset.X - lt.X, offset.Y - lt.Y)); - g.Flush(); + int w = r - l; + int h = b - t; + if (l != offsetX || t != offsetY || w != surface.Width || h != surface.Height) { + Cairo.ImageSurface newSurface = new Cairo.ImageSurface(Cairo.Format.ARGB32, w, h); + Cairo.Context context = new Cairo.Context(newSurface); + context.Translate(offsetX - l, offsetY - t); + context.SetSource(surface); + context.Paint(); + context.GetTarget().Flush(); + context.Dispose(); + surface.Dispose(); - offset = lt; - bitmap = newBitmap; + offsetX = l; + offsetY = t; + surface = newSurface; } } - private Graphics getGraphics() { - Graphics g = Graphics.FromImage(bitmap); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.TranslateTransform(-offset.X, -offset.Y); - return g; + private Cairo.Context getContext() { + Cairo.Context context = new Cairo.Context(surface); + context.Antialias = Cairo.Antialias.Gray; + context.Translate(-offsetX, -offsetY); + return context; } public void paintTrack(Track track) { expand(track.getBounds()); - Graphics g = getGraphics(); - track.draw(g); - g.Flush(); + Cairo.Context context = getContext(); + track.draw(context); + context.GetTarget().Flush(); + context.Dispose(); } } } diff --git a/mono/Assistance/Document.cs b/mono/Assistance/Document.cs index fb6dd89..ef232d0 100644 --- a/mono/Assistance/Document.cs +++ b/mono/Assistance/Document.cs @@ -1,6 +1,4 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; using System.Linq; diff --git a/mono/Assistance/Drawing.cs b/mono/Assistance/Drawing.cs new file mode 100644 index 0000000..fa3f972 --- /dev/null +++ b/mono/Assistance/Drawing.cs @@ -0,0 +1,85 @@ +using System; + +namespace Assistance { + namespace Drawing { + public class Helper { + public static Rectangle getBounds(Cairo.Context context) { + double w = 1.0; + double h = 1.0; + if (context.GetTarget() is Cairo.ImageSurface) { + Cairo.ImageSurface surface = (Cairo.ImageSurface)context.GetTarget(); + w = surface.Width; + h = surface.Height; + } + + Point[] corners = new Point[] { + new Point(0.0, 0.0), + new Point( w, 0.0), + new Point( w, h), + new Point(0.0, h) }; + + Rectangle bounds = new Rectangle(); + for(int i = 0; i < corners.Length; ++i) { + double x = corners[i].x; + double y = corners[i].y; + context.DeviceToUser(ref x, ref y); + if (i == 0) + bounds = new Rectangle(x, y); + else + bounds = bounds.expand(new Point(x, y)); + } + + return bounds; + } + } + + + public struct Color { + public double r, g, b, a; + public Color(string name, double alpha = 1.0) { + Gdk.Color c = new Gdk.Color(); + if (!Gdk.Color.Parse(name, ref c)) + Console.Error.WriteLine("Color [" + name + "] not found"); + this.r = (double)c.Red/65535.0; + this.g = (double)c.Green/65535.0; + this.b = (double)c.Blue/65535.0; + this.a = alpha; + } + public Color(double r, double g, double b, double a = 1.0) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + public void apply(Cairo.Context context) { + context.SetSourceRGBA(r, g, b, a); + } + } + + + public struct Pen { + public Color color; + public double width; + public Pen(string color, double width = 1.0, double alpha = 1.0) { + this.color = new Color(color, alpha); + this.width = width; + } + public void apply(Cairo.Context context) { + color.apply(context); + context.LineWidth = width; + } + } + + + public struct Brush { + public Color color; + public Brush(string color, double alpha = 1.0) { + this.color = new Color(color, alpha); + } + public void apply(Cairo.Context context) { + color.apply(context); + } + } + } +} + diff --git a/mono/Assistance/Geometry.cs b/mono/Assistance/Geometry.cs index 91fc0ed..f9d248b 100644 --- a/mono/Assistance/Geometry.cs +++ b/mono/Assistance/Geometry.cs @@ -1,6 +1,4 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; namespace Assistance { @@ -45,6 +43,13 @@ namespace Assistance { return p; } + public static double splinePoint(double p0, double p1, double t0, double t1, double l) { + return p0*(( 2.0*l - 3.0)*l*l + 1.0) + + p1*((-2.0*l + 3.0)*l*l ) + + t0*(( l - 2.0)*l*l + l ) + + t1*(( l - 1.0)*l*l ); + } + public static Point splinePoint(Point p0, Point p1, Point t0, Point t1, double l) { return p0*(( 2.0*l - 3.0)*l*l + 1.0) + p1*((-2.0*l + 3.0)*l*l ) diff --git a/mono/Assistance/Guideline.cs b/mono/Assistance/Guideline.cs index 95ecc37..923ac19 100644 --- a/mono/Assistance/Guideline.cs +++ b/mono/Assistance/Guideline.cs @@ -1,12 +1,11 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; +using Assistance.Drawing; namespace Assistance { public class Guideline { - public static readonly Pen pen = Pens.LightGray; - public static readonly Pen penActive = Pens.DeepSkyBlue; + public static readonly Pen pen = new Pen("Light Gray"); + public static readonly Pen penActive = new Pen("Deep Sky Blue"); public static readonly double snapLenght = 20.0; public static readonly double snapScale = 1.0; @@ -14,10 +13,10 @@ namespace Assistance { return p; } - public virtual void draw(Graphics g, bool active) { } + public virtual void draw(Cairo.Context context, bool active) { } - public void draw(Graphics g) { - draw(g, false); + public void draw(Cairo.Context context) { + draw(context, false); } public double calcTrackWeight(Track track) { @@ -27,8 +26,9 @@ namespace Assistance { double sumLength = 0.0; double sumDeviation = 0.0; - Point prev = track.points[0]; - foreach(Point p in track.points) { + Point prev = track.points[0].point; + foreach(TrackPoint tp in track.points) { + Point p = tp.point; double length = (p - prev).len(); sumLength += length; diff --git a/mono/Assistance/GuidelineLine.cs b/mono/Assistance/GuidelineLine.cs index 8d49133..cb67efd 100644 --- a/mono/Assistance/GuidelineLine.cs +++ b/mono/Assistance/GuidelineLine.cs @@ -1,6 +1,4 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; namespace Assistance { @@ -14,11 +12,18 @@ namespace Assistance { direction = (p1 - p0).normalize(); } - public override void draw(Graphics g, bool active) { + public override void draw(Cairo.Context context, bool active) { Point pp0 = p0; Point pp1 = p1; - Geometry.truncateInfiniteLine(new Rectangle(g.VisibleClipBounds), ref pp0, ref pp1); - g.DrawLine(active ? penActive : pen , pp0.toFloat(), pp1.toFloat()); + Rectangle bounds = Drawing.Helper.getBounds(context); + Geometry.truncateInfiniteLine(bounds, ref pp0, ref pp1); + + context.Save(); + (active ? penActive : pen).apply(context); + context.MoveTo(pp0.x, pp0.y); + context.LineTo(pp1.x, pp1.y); + context.Stroke(); + context.Restore(); } public override Point transformPoint(Point p) { diff --git a/mono/Assistance/MainWindow.cs b/mono/Assistance/MainWindow.cs index c888249..350c30d 100644 --- a/mono/Assistance/MainWindow.cs +++ b/mono/Assistance/MainWindow.cs @@ -1,49 +1,79 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; -using System.Windows.Forms; using System.Collections.Generic; namespace Assistance { - public class MainWindow : Form { - static public void Main() { Application.Run(new MainWindow()); } + public class MainWindow : Gtk.Window { + static public void Main() { + Gtk.Application.Init(); + MainWindow win = new MainWindow(); + win.Show(); + Gtk.Application.Run(); + } + + Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, 1, 1); - Bitmap bitmap = new Bitmap(1, 1); Workarea workarea = new Workarea(); bool dragging = false; ActivePoint activePoint; + + uint timeStart = 0; Point offset; Point cursor; Track track = null; - public MainWindow() { - Paint += onPaint; - MouseMove += onMouseMove; - MouseDown += onMouseDown; - MouseUp += onMouseUp; - KeyDown += onKeyDown; - WindowState = FormWindowState.Maximized; + public MainWindow(): base(Gtk.WindowType.Toplevel) { + this.Events = Gdk.EventMask.KeyPressMask + | Gdk.EventMask.KeyReleaseMask + | Gdk.EventMask.ButtonPressMask + | Gdk.EventMask.ButtonReleaseMask + | Gdk.EventMask.ButtonMotionMask + | Gdk.EventMask.PointerMotionMask; + Maximize(); } + + protected override bool OnDeleteEvent(Gdk.Event e) { + Gtk.Application.Quit(); + return true; + } - protected override void OnPaintBackground(PaintEventArgs e) { } + protected override void OnSizeAllocated(Gdk.Rectangle allocation) { + if ( surface.Width != allocation.Width + || surface.Height != allocation.Height ) + { + surface.Dispose(); + surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, allocation.Width, allocation.Height); + } + base.OnSizeAllocated(allocation); + } - public void onPaint(Object sender, PaintEventArgs e) { - if (bitmap.Size != ClientSize) - bitmap = new Bitmap(ClientSize.Width, ClientSize.Height); - Graphics g = Graphics.FromImage(bitmap); - g.Clear(Color.White); - draw(g); - g.Flush(); - e.Graphics.DrawImageUnscaled(bitmap, 0, 0); - } + protected override bool OnExposeEvent(Gdk.EventExpose e) { + Cairo.Context context = new Cairo.Context(surface); + context.Antialias = Cairo.Antialias.Gray; + + context.Save(); + context.SetSourceRGBA(1.0, 1.0, 1.0, 1.0); + context.Rectangle(0, 0, surface.Width, surface.Height); + context.Fill(); + context.Restore(); + + draw(context); + context.Dispose(); + + context = Gdk.CairoHelper.Create(GdkWindow); + context.SetSource(surface); + context.Paint(); + context.Dispose(); + + return true; + } public Point windowToWorkarea(Point p) { - return new Point(p.x - ClientSize.Width/2.0, p.y - ClientSize.Height/2.0); + return new Point(p.x - surface.Width/2.0, p.y - surface.Height/2.0); } public Point workareaToWindow(Point p) { - return new Point(p.x + ClientSize.Width/2.0, p.y + ClientSize.Height/2.0); + return new Point(p.x + surface.Width/2.0, p.y + surface.Height/2.0); } private void beginDrag() { @@ -66,68 +96,100 @@ namespace Assistance { workarea.paintTrack(track); track = null; } - - public void onKeyDown(Object sender, KeyEventArgs e) { - switch(e.KeyCode) { - case Keys.D1: + + protected override bool OnKeyPressEvent(Gdk.EventKey e) { + switch(e.Key) { + case Gdk.Key.Key_1: new AssistantVanishingPoint(workarea.document, cursor); break; - case Keys.D2: + case Gdk.Key.Key_2: new AssistantGrid(workarea.document, cursor); break; - case Keys.Q: + case Gdk.Key.Q: + case Gdk.Key.q: new ModifierSnowflake(workarea.document, cursor); break; - case Keys.Delete: + case Gdk.Key.Delete: if (activePoint != null) activePoint.owner.remove(); endDragAndTrack(); break; } endDragAndTrack(); - Invalidate(); + QueueDraw(); + return base.OnKeyPressEvent(e); + } + + TrackPoint makeTrackPoint(double x, double y, uint time, Gdk.Device device, double[] axes) { + TrackPoint point = new TrackPoint( + windowToWorkarea(new Point(x, y)), + (double)(time - timeStart)*0.001 ); + if (device != null && axes != null) { + double v; + if (device.GetAxis(axes, Gdk.AxisUse.Pressure, out v)) + point.pressure = v; + if (device.GetAxis(axes, Gdk.AxisUse.Xtilt, out v)) + point.tilt.x = v; + if (device.GetAxis(axes, Gdk.AxisUse.Ytilt, out v)) + point.tilt.y = v; + } + return point; + } + + TrackPoint makeTrackPoint(Gdk.EventButton e) { + return makeTrackPoint(e.X, e.Y, e.Time, e.Device, e.Axes); } - public void onMouseDown(Object sender, MouseEventArgs e) { - cursor = windowToWorkarea(new Point(e.Location.X, e.Location.Y)); - if (e.Button == MouseButtons.Left) { + TrackPoint makeTrackPoint(Gdk.EventMotion e) { + return makeTrackPoint(e.X, e.Y, e.Time, e.Device, e.Axes); + } + + protected override bool OnButtonPressEvent(Gdk.EventButton e) { + cursor = windowToWorkarea(new Point(e.X, e.Y)); + if (e.Button == 1) { + timeStart = e.Time; activePoint = workarea.findPoint(cursor); if (activePoint != null) { beginDrag(); } else { beginTrack(); - track.points.Add(cursor); + track.points.Add(makeTrackPoint(e)); } } - Invalidate(); + QueueDraw(); + return true; } - public void onMouseUp(Object sender, MouseEventArgs e) { + protected override bool OnButtonReleaseEvent(Gdk.EventButton e) { cursor = windowToWorkarea(new Point(e.X, e.Y)); - if (e.Button == MouseButtons.Left) + if (e.Button == 1) { + if (!dragging && track != null) + track.points.Add(makeTrackPoint(e)); endDragAndTrack(); - if (!dragging && track == null) - activePoint = workarea.findPoint(cursor); - Invalidate(); + if (!dragging && track == null) + activePoint = workarea.findPoint(cursor); + } + QueueDraw(); + return true; } - public void onMouseMove(Object sender, MouseEventArgs e) { - cursor = windowToWorkarea(new Point(e.Location.X, e.Location.Y)); + protected override bool OnMotionNotifyEvent(Gdk.EventMotion e) { + cursor = windowToWorkarea(new Point(e.X, e.Y)); if (dragging) { activePoint.owner.onMovePoint(activePoint, cursor + offset); } else if (track != null) { - track.points.Add(cursor); + track.points.Add(makeTrackPoint(e)); } else { activePoint = workarea.findPoint(cursor); } - Invalidate(); - } + QueueDraw(); + return true; + } - public void draw(Graphics g) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.TranslateTransform(ClientSize.Width/2, ClientSize.Height/2); - workarea.draw(g, activePoint, cursor + offset, track); + public void draw(Cairo.Context context) { + context.Translate(surface.Width/2, surface.Height/2); + workarea.draw(context, activePoint, cursor + offset, track); } } } diff --git a/mono/Assistance/Modifier.cs b/mono/Assistance/Modifier.cs index 663d6c2..5337b5c 100644 --- a/mono/Assistance/Modifier.cs +++ b/mono/Assistance/Modifier.cs @@ -1,11 +1,10 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; +using Assistance.Drawing; namespace Assistance { public class Modifier: ActivePoint.Owner { - public static readonly Pen pen = Pens.LightGray; + public static readonly Pen pen = new Pen("Light Gray"); public Modifier(Document document): base(document) { document.modifiers.Add(this); @@ -21,7 +20,7 @@ namespace Assistance { document.modifiers.Add(this); } - public virtual void draw(Graphics g) { } + public virtual void draw(Cairo.Context context) { } public virtual void getTransformFuncs(List transformFuncs) { } diff --git a/mono/Assistance/ModifierSnowflake.cs b/mono/Assistance/ModifierSnowflake.cs index 3b50176..ed311e8 100644 --- a/mono/Assistance/ModifierSnowflake.cs +++ b/mono/Assistance/ModifierSnowflake.cs @@ -1,6 +1,4 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; namespace Assistance { @@ -13,12 +11,19 @@ namespace Assistance { this.center = new ActivePoint(this, ActivePoint.Type.CircleCross, center); } - public override void draw(System.Drawing.Graphics g) { + public override void draw(Cairo.Context context) { for(int i = 0; i < rays/2; ++i) { Point pp0 = center.position; Point pp1 = center.position + new Point(100.0, 0.0).rotate( i*2.0*Math.PI/(double)rays ); - Geometry.truncateInfiniteLine(new Rectangle(g.VisibleClipBounds), ref pp0, ref pp1); - g.DrawLine(pen, pp0.toFloat(), pp1.toFloat()); + Rectangle bounds = Drawing.Helper.getBounds(context); + Geometry.truncateInfiniteLine(bounds, ref pp0, ref pp1); + + context.Save(); + pen.apply(context); + context.MoveTo(pp0.x, pp0.y); + context.LineTo(pp1.x, pp1.y); + context.Stroke(); + context.Restore(); } } diff --git a/mono/Assistance/Point.cs b/mono/Assistance/Point.cs index e931004..7814c8b 100644 --- a/mono/Assistance/Point.cs +++ b/mono/Assistance/Point.cs @@ -9,46 +9,26 @@ namespace Assistance { this.x = x; this.y = y; } - public Point(System.Drawing.Point point): - this(point.X, point.Y) { } - public Point(System.Drawing.PointF point): - this(point.X, point.Y) { } - public static Point operator+ (Point a, Point b) { - return new Point(a.x + b.x, a.y + b.y); - } - - public static Point operator- (Point a, Point b) { - return new Point(a.x - b.x, a.y - b.y); - } - - public static Point operator* (Point a, double b) { - return new Point(a.x*b, a.y*b); - } - - public static Point operator* (double b, Point a) { - return a*b; - } - - public static Point operator/ (Point a, double b) { - return new Point(a.x/b, a.y/b); - } - - public static double dot(Point a, Point b) { - return a.x*b.x + a.y*b.y; - } - - public bool isEqual(Point other) { - return (this - other).lenSqr() <= Geometry.precision*Geometry.precision; - } - - public double lenSqr() { - return x*x + y*y; - } - - public double len() { - return Math.Sqrt(lenSqr()); - } + public static Point operator+ (Point a, Point b) + { return new Point(a.x + b.x, a.y + b.y); } + public static Point operator- (Point a, Point b) + { return new Point(a.x - b.x, a.y - b.y); } + public static Point operator* (Point a, double b) + { return new Point(a.x*b, a.y*b); } + public static Point operator* (double b, Point a) + { return a*b; } + public static Point operator/ (Point a, double b) + { return new Point(a.x/b, a.y/b); } + public static double dot(Point a, Point b) + { return a.x*b.x + a.y*b.y; } + + public bool isEqual(Point other) + { return (this - other).lenSqr() <= Geometry.precision*Geometry.precision; } + public double lenSqr() + { return x*x + y*y; } + public double len() + { return Math.Sqrt(lenSqr()); } public Point normalize() { double l = len(); @@ -60,14 +40,6 @@ namespace Assistance { double c = Math.Cos(angle); return new Point(c*x - s*y, s*x + c*y); } - - public System.Drawing.PointF toFloat() { - return new System.Drawing.PointF((float)x, (float)y); - } - - public System.Drawing.Point toInt() { - return new System.Drawing.Point((int)Math.Floor(x), (int)Math.Floor(y)); - } } } diff --git a/mono/Assistance/Rectangle.cs b/mono/Assistance/Rectangle.cs index 68324e8..247c604 100644 --- a/mono/Assistance/Rectangle.cs +++ b/mono/Assistance/Rectangle.cs @@ -40,10 +40,6 @@ namespace Assistance { this(p.x, p.y) { } public Rectangle(Point p0, Point p1): this(p0.x, p0.y, p1.x, p1.y) { } - public Rectangle(System.Drawing.Rectangle rect): - this(rect.Left, rect.Top, rect.Right, rect.Bottom) { } - public Rectangle(System.Drawing.RectangleF rect): - this(rect.Left, rect.Top, rect.Right, rect.Bottom) { } public Rectangle expand(Point p, double radius = 0.0) { return new Rectangle( @@ -84,23 +80,6 @@ namespace Assistance { Math.Min(a.y1, b.y1) ); return rect.empty ? new Rectangle() : rect; } - - public System.Drawing.Rectangle toInt() { - System.Drawing.Rectangle rect = new System.Drawing.Rectangle( - (int)Math.Floor(x0), - (int)Math.Floor(y0), - (int)Math.Ceiling(x1) - (int)Math.Floor(x0), - (int)Math.Ceiling(y1) - (int)Math.Floor(y0) ); - if (empty) { - rect.Width = Math.Min(0, rect.Width); - rect.Height = Math.Min(0, rect.Height); - } - return rect; - } - - public System.Drawing.RectangleF toFloat() { - return new System.Drawing.RectangleF((float)x0, (float)y0, (float)(x1 - x0), (float)(y1 - y0)); - } } } diff --git a/mono/Assistance/Track.cs b/mono/Assistance/Track.cs index c8e1d7f..96c5b5f 100644 --- a/mono/Assistance/Track.cs +++ b/mono/Assistance/Track.cs @@ -1,14 +1,13 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; +using Assistance.Drawing; namespace Assistance { public class Track { - public static readonly Pen pen = new Pen(Brushes.DarkGreen, 3f); - public static readonly Pen penPreview = new Pen(new SolidBrush(Color.FromArgb(64, Color.DarkGreen)), 1f); + public static readonly Pen pen = new Pen("Dark Green", 3.0); + public static readonly Pen penPreview = new Pen("Dark Green", 1.0, 0.25); - public readonly List points = new List(); + public readonly List points = new List(); private readonly List parents = new List(); private readonly List transformFuncs = new List(); @@ -41,23 +40,34 @@ namespace Assistance { public Rectangle getBounds() { if (points.Count == 0) return new Rectangle(); - Rectangle bounds = new Rectangle(points[0]); - foreach(Point p in points) - bounds = bounds.expand(p); - return bounds.inflate(Math.Max(pen.Width, penPreview.Width) + 2.0); + Rectangle bounds = new Rectangle(points[0].point); + foreach(TrackPoint p in points) + bounds = bounds.expand(p.point); + return bounds.inflate(Math.Max(pen.width, penPreview.width) + 2.0); } - public Point transform(Point p) { - return Geometry.transform(transformFuncs, p); + public TrackPoint transform(TrackPoint p) { + p.point = Geometry.transform(transformFuncs, p.point); + return p; } - private void addSpline(Point p0, Point p1, Point t0, Point t1, Point tp0, Point tp1, double l0, double l1, double precisionSqr) { - if ((tp1 - tp0).lenSqr() < precisionSqr) { + private void addSpline( + TrackPoint p0, TrackPoint p1, + TrackPoint t0, TrackPoint t1, + TrackPoint tp0, TrackPoint tp1, + double l0, double l1, + double precisionSqr + ) { + if ((tp1.point - tp0.point).lenSqr() < precisionSqr) { points.Add(tp1); } else { double l = 0.5*(l0 + l1); - Point p = Geometry.splinePoint(p0, p1, t0, t1, l); - Point tp = transform(p); + TrackPoint p = new TrackPoint( + Geometry.splinePoint(p0.point, p1.point, t0.point, t1.point, l), + p0.time + l*(p1.time - p0.time), + Geometry.splinePoint(p0.pressure, p1.pressure, t0.pressure, t1.pressure, l), + Geometry.splinePoint(p0.tilt, p1.tilt, t0.tilt, t1.tilt, l) ); + TrackPoint tp = transform(p); addSpline(p0, p1, t0, t1, tp0, tp, l0, l, precisionSqr); addSpline(p0, p1, t0, t1, tp, tp1, l, l1, precisionSqr); } @@ -70,21 +80,24 @@ namespace Assistance { Track root = parents[0]; if (root.points.Count < 2) { - foreach(Point p in root.points) - points.Add( Geometry.transform(transformFuncs, p) ); + foreach(TrackPoint p in root.points) + points.Add( transform(p) ); return; } double precisionSqr = precision * precision; - Point p0 = root.points[0]; - Point p1 = root.points[1]; - Point t0 = 0.5*(p1 - p0); - Point tp0 = Geometry.transform(transformFuncs, p0); + TrackPoint p0 = root.points[0]; + TrackPoint p1 = root.points[1]; + TrackPoint t0 = new TrackPoint(); + TrackPoint tp0 = transform(p0); points.Add(tp0); for(int i = 1; i < root.points.Count; ++i) { - Point p2 = root.points[i+1 < root.points.Count ? i+1 : i]; - Point tp1 = Geometry.transform(transformFuncs, p1); - Point t1 = 0.5*(p2 - p0); + TrackPoint p2 = root.points[i+1 < root.points.Count ? i+1 : i]; + TrackPoint tp1 = transform(p1); + double dt = p2.time - p0.time; + TrackPoint t1 = dt > Geometry.precision + ? (p2 - p0)*(p1.time - p0.time)/dt + : new TrackPoint(); addSpline(p0, p1, t0, t1, tp0, tp1, 0.0, 1.0, precisionSqr); p0 = p1; @@ -94,13 +107,16 @@ namespace Assistance { } } - public void draw(Graphics g, bool preview = false) { + public void draw(Cairo.Context context, bool preview = false) { if (points.Count < 2) return; - PointF[] ps = new PointF[points.Count]; - for(int i = 0; i < ps.Length; ++i) - ps[i] = points[i].toFloat(); - g.DrawLines(preview ? penPreview : pen, ps); + context.Save(); + (preview ? penPreview : pen).apply(context); + context.MoveTo(points[0].point.x, points[0].point.y); + for(int i = 1; i < points.Count; ++i) + context.LineTo(points[i].point.x, points[i].point.y); + context.Stroke(); + context.Restore(); } } } diff --git a/mono/Assistance/TrackPoint.cs b/mono/Assistance/TrackPoint.cs new file mode 100644 index 0000000..f8a5c59 --- /dev/null +++ b/mono/Assistance/TrackPoint.cs @@ -0,0 +1,29 @@ +using System; + +namespace Assistance { + public struct TrackPoint { + public Point point; + public double time; + public double pressure; + public Point tilt; + + public TrackPoint(Point point, double time, double pressure = 0.5, Point tilt = new Point()) { + this.point = point; + this.time = time; + this.pressure = pressure; + this.tilt = tilt; + } + + public static TrackPoint operator+ (TrackPoint a, TrackPoint b) + { return new TrackPoint(a.point + b.point, a.time + b.time, a.pressure + b.pressure, a.tilt + b.tilt); } + public static TrackPoint operator- (TrackPoint a, TrackPoint b) + { return new TrackPoint(a.point - b.point, a.time - b.time, a.pressure - b.pressure, a.tilt - b.tilt); } + public static TrackPoint operator* (TrackPoint a, double b) + { return new TrackPoint(a.point*b, a.time*b, a.pressure*b, a.tilt*b); } + public static TrackPoint operator* (double b, TrackPoint a) + { return a*b; } + public static TrackPoint operator/ (TrackPoint a, double b) + { return new TrackPoint(a.point/b, a.time/b, a.pressure/b, a.tilt/b); } + } +} + diff --git a/mono/Assistance/Workarea.cs b/mono/Assistance/Workarea.cs index 4c5af83..90ced8b 100644 --- a/mono/Assistance/Workarea.cs +++ b/mono/Assistance/Workarea.cs @@ -1,6 +1,4 @@ using System; -using System.Drawing; -using System.Drawing.Imaging; using System.Collections.Generic; using System.Linq; @@ -8,9 +6,6 @@ namespace Assistance { public class Workarea { public readonly Document document; - // TODO: remove this? - public ActivePoint ActivePoint = null; - public Workarea() { document = new Document(this); } @@ -27,9 +22,9 @@ namespace Assistance { assistant.getGuidelines(outGuidelines, target); } - public void draw(Graphics g, ActivePoint activePoint, Point target, Track track) { + public void draw(Cairo.Context context, ActivePoint activePoint, Point target, Track track) { // canvas - document.canvas.draw(g); + document.canvas.draw(context); // guidelines and track List guidelines = new List(); @@ -37,33 +32,34 @@ namespace Assistance { Guideline guideline; Track modifiedTrack = modifyTrackByAssistant(track, out guideline); - getGuidelines(guidelines, modifiedTrack.transform(track.points.Last())); - foreach(Guideline gl in guidelines) gl.draw(g); + getGuidelines(guidelines, modifiedTrack.transform(track.points.Last()).point); + foreach(Guideline gl in guidelines) + gl.draw(context); - track.draw(g, true); - if (guideline != null) guideline.draw(g, true); + track.draw(context, true); + if (guideline != null) guideline.draw(context, true); List modifiedTracks = modifyTrackByModifiers(modifiedTrack); rebuildTracks(modifiedTracks); foreach(Track t in modifiedTracks) - t.draw(g); + t.draw(context); } else { getGuidelines(guidelines, target); foreach(Guideline guideline in guidelines) - guideline.draw(g); + guideline.draw(context); } // modifiers foreach(Modifier modifier in document.modifiers) - modifier.draw(g); + modifier.draw(context); // assistants foreach(Assistant assistant in document.assistants) - assistant.draw(g); + assistant.draw(context); // active points foreach(ActivePoint point in document.points) - point.draw(g, activePoint == point); + point.draw(context, activePoint == point); } public Track modifyTrackByAssistant(Track track, out Guideline guideline) { @@ -72,7 +68,7 @@ namespace Assistance { return track.createChild(Geometry.noTransform); List guidelines = new List(); - getGuidelines(guidelines, track.points[0]); + getGuidelines(guidelines, track.points[0].point); guideline = Guideline.findBest(guidelines, track); if (guideline == null) return track.createChild(Geometry.noTransform);