public override void DrawArc(double x1, double y1, double x2, double y2, double bulge) { if (thinlinemode != ThinLineModeFlag.OwnThinLines) { base.DrawArc(x1, y1, x2, y2, bulge); return; } stipplebit = 0x8000; int clipres = Clipper.ClipArc(x1, y1, x2, y2, bulge, clipbuffer, clipMinX, clipMinY, clipMaxX, clipMaxY); for (int idx = 0; idx < clipres; idx += 5) { int cx = GFXUtil.FloatToInt(clipbuffer[idx]), cy = GFXUtil.FloatToInt(clipbuffer[idx + 1]), nx, ny; GeomUtil.FlattenArc(clipbuffer[idx], clipbuffer[idx + 1], clipbuffer[idx + 2], clipbuffer[idx + 3], clipbuffer[idx + 4], false, flattentol, (x, y, moveto) => { nx = GFXUtil.FloatToInt(x); ny = GFXUtil.FloatToInt(y); Line_Internal(cx, cy, nx, ny, x2 == x && y2 == y); //set last point if last segment cx = nx; cy = ny; }); } }
public override void DrawLine(double x1, double y1, double x2, double y2) { if (thinlinemode != ThinLineModeFlag.OwnThinLines) { base.DrawLine(x1, y1, x2, y2); return; } stipplebit = 0x8000; Line_Internal(GFXUtil.FloatToInt(x1), GFXUtil.FloatToInt(y1), GFXUtil.FloatToInt(x2), GFXUtil.FloatToInt(y2), true); }
public override void DrawEllipticArc(double cx, double cy, double aradius, double bradius, double tilt, double startangle, double sweepangle) { if (thinlinemode != ThinLineModeFlag.OwnThinLines) { base.DrawEllipticArc(cx, cy, aradius, bradius, tilt, startangle, sweepangle); return; } /* stipplebit = 0x8000; * * int px=0,py=0,nx,ny; * bool first = true; * * GeomUtil.FlattenEllipticArc(cx, cy, aradius, bradius, tilt, startangle, sweepangle, flattentol, true, (x, y,moveto) => * { * nx = GFXUtil.RealToInt(x); * ny = GFXUtil.RealToInt(y); * if (!first) * Line_Internal(px, py, nx, ny, true); //TODO: can we skip last pixel except on last segment? * else * first = false; * * * px = nx; * py = ny; * });*/ int px = 0, py = 0, nx, ny; int num = Clipper.ClipEllipticArc(cx, cy, aradius, bradius, tilt, startangle, sweepangle, clipbuffer, clipMinX, clipMinY, clipMaxX, clipMaxY); for (int l = 0; l < num; l += 2) { stipplebit = 0x8000; GeomUtil.FlattenEllipticArc(cx, cy, aradius, bradius, tilt, clipbuffer[l], clipbuffer[l + 1] - clipbuffer[l], flattentol, true, (x, y, moveto) => { nx = GFXUtil.FloatToInt(x); ny = GFXUtil.FloatToInt(y); if (!moveto) { Line_Internal(px, py, nx, ny, true); //TODO: can we skip last pixel except on last segment? } px = nx; py = ny; }); } }
public override void DrawRectangleT(double x1, double y1, double x2, double y2) { if (thinlinemode != ThinLineModeFlag.OwnThinLines) { base.DrawRectangleT(x1, y1, x2, y2); return; } stipplebit = 0x8000; //convert to four points as poly to be able to transform double x3 = x2; double y3 = y2; y2 = y1; double x4 = x1; double y4 = y3; Transform.Apply(x1, y1, out x1, out y1, true); Transform.Apply(x2, y2, out x2, out y2, true); Transform.Apply(x3, y3, out x3, out y3, true); Transform.Apply(x4, y4, out x4, out y4, true); int ix1 = GFXUtil.FloatToInt(x1); int iy1 = GFXUtil.FloatToInt(y1); int ix2 = GFXUtil.FloatToInt(x2); int iy2 = GFXUtil.FloatToInt(y2); int ix3 = GFXUtil.FloatToInt(x3); int iy3 = GFXUtil.FloatToInt(y3); int ix4 = GFXUtil.FloatToInt(x4); int iy4 = GFXUtil.FloatToInt(y4); //check for pixel sized rectangle if (ix1 == ix2 && ix2 == ix3 && ix3 == ix4 && iy1 == iy2 && iy2 == iy3 && iy3 == iy4) { SetPixel(ix1, iy1, color); return; } Line_Internal(ix1, iy1, ix2, iy2, false); Line_Internal(ix2, iy2, ix3, iy3, false); Line_Internal(ix3, iy3, ix4, iy4, false); Line_Internal(ix4, iy4, ix1, iy1, false); }
public override void DrawPolyLine(bool close, params double[] xy) { if (thinlinemode != ThinLineModeFlag.OwnThinLines) { base.DrawPolyLine(close, xy); return; } stipplebit = 0x8000; int n = xy.Length; if (xy.Length < 2) { return; } int prevx = GFXUtil.FloatToInt(xy[0]); int prevy = GFXUtil.FloatToInt(xy[1]); int firstx = prevx; int firsty = prevy; int lastidx = n - 2; for (int l = 0; l < n;) { bool lastpixel = l == lastidx; int nextx = GFXUtil.FloatToInt(xy[l++]); int nexty = GFXUtil.FloatToInt(xy[l++]); Line_Internal(prevx, prevy, nextx, nexty, lastpixel); prevx = nextx; prevy = nexty; } if (close) { Line_Internal(prevx, prevy, firstx, firsty, false); } }
private void InternalDrawBezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { int n = Clipper.ClipBezier(x1, y1, x2, y2, x3, y3, x4, y4, clipbuffer, clipMinX, clipMinY, clipMaxX, clipMaxY); int penx = 0, peny = 0; for (int l = 0; l < n; l += 2) { GeomUtil.FlattenBezier(x1, y1, x2, y2, x3, y3, x4, y4, true, flattentol, (x, y, moveto) => { int nextx = GFXUtil.FloatToInt(x); int nexty = GFXUtil.FloatToInt(y); if (!moveto) { Line_Internal(penx, peny, nextx, nexty, false); } penx = nextx; peny = nexty; }, clipbuffer[l], clipbuffer[l + 1]); } }
public override void DrawRectangle(double x1, double y1, double x2, double y2) { if (thinlinemode != ThinLineModeFlag.OwnThinLines) { base.DrawRectangle(x1, y1, x2, y2); return; } stipplebit = 0x8000; int ix1 = GFXUtil.FloatToInt(x1); int iy1 = GFXUtil.FloatToInt(y1); int ix2 = GFXUtil.FloatToInt(x2); int iy2 = GFXUtil.FloatToInt(y2); if (ix1 == ix2) { if (iy1 == iy2) { SetPixel(ix1, iy1, color); return; } else { Line_Internal(ix1, iy1, ix1, iy2, true); //vertical line return; } } else if (iy1 == iy2) { Line_Internal(ix1, iy1, ix2, iy1, true); //horizontal line return; } Line_Internal(ix1, iy1, ix2, iy1, false); Line_Internal(ix2, iy1, ix2, iy2, false); Line_Internal(ix2, iy2, ix1, iy2, false); Line_Internal(ix1, iy2, ix1, iy1, false); }
/// <summary> /// Create a GDI+ Pen that corresponds to a Painter setup /// </summary> /// <param name="p"></param> /// <returns></returns> public static Pen CreateLinePenFromPainter(Painter p) { Color c = PainterGDIPlus.RGBToColor(p.Color); if (p.Opacity < 0.999) { c = Color.FromArgb(GFXUtil.FloatToInt(MathUtil.Clamp(p.Opacity * 255.0, 0.0, 255.0)), c); } Pen linepen = new Pen(c, (float)Math.Abs(p.LineWidth)); //0 means the thinnest possible on device switch (p.LineStyle) { case LineStyle.Continuous: break; //done already case LineStyle.Custom: SetCustomDashes(p.LineStyleDashes, p.LineWidth, linepen); linepen.DashStyle = DashStyle.Custom; break; case LineStyle.Dash: linepen.DashPattern = new float[] { 8, 8 }; linepen.DashStyle = DashStyle.Custom; break; case LineStyle.DashDotDot: linepen.DashPattern = new float[] { 7, 2, 2, 1, 2, 2 }; linepen.DashStyle = DashStyle.Custom; break; case LineStyle.DashDot: linepen.DashPattern = new float[] { 8, 3, 2, 3 }; linepen.DashStyle = DashStyle.Custom; break; case LineStyle.Dot: linepen.DashPattern = new float[] { 4, 4 }; linepen.DashStyle = DashStyle.Custom; break; } /* if (p.LineStyle != LineStyle.Continuous) * { * //linepen.DashStyle = LineStyleToDashStyle(p.LineStyle); * linepen.DashStyle = DashStyle.Custom; * if (p.LineStyle == LineStyle.Custom) * SetCustomDashes(p.LineStyleDashes, linepen); * else if (p.LineStyle == LineStyle.Dot) * linepen.DashPattern = new float[] { 4, 4 }; * else * linepen.DashPattern = new float[] { 10, 4, 4, 4 }; * * * * } */ LineCap ecap; DashCap dcap; if (p.EndCaps != EndCap.Flat) //flat is default for pen and thus need no change { GetEndCap(p.EndCaps, out ecap, out dcap); linepen.EndCap = ecap; linepen.StartCap = ecap; linepen.DashCap = dcap; } if (p.LineJoin != LineJoin.Miter) //miter is default and thus needs no change { linepen.LineJoin = GetLineJoin(p.LineJoin); } return(linepen); }
public override void DrawCircle(double cx, double cy, double radius) { if (thinlinemode != ThinLineModeFlag.OwnThinLines) { base.DrawCircle(cx, cy, radius); return; } stipplebit = 0x8000; int nx = 0, ny = 0, px = 0, py = 0; int buffersize = Clipper.ClipCircle(cx, cy, radius, clipbuffer, clipMinX, clipMinY, clipMaxX, clipMaxY); if (buffersize <= 0) { return; } if (buffersize >= 5) //circle is clipped to arcs { //the circle is divided into arc(s) double bulge, x1, y1, x2, y2; for (int l = 0; l < buffersize; l += 5) { x1 = clipbuffer[l]; y1 = clipbuffer[l + 1]; x2 = clipbuffer[l + 2]; y2 = clipbuffer[l + 3]; bulge = clipbuffer[l + 4]; //draw arc here instead of calling DrawArc to avoid arc clipping because we already clipped! GeomUtil.FlattenArc(x1, y1, x2, y2, bulge, true, flattentol, (x, y, moveto) => { if (moveto) { px = GFXUtil.FloatToInt(x); py = GFXUtil.FloatToInt(y); } else { nx = GFXUtil.FloatToInt(x); ny = GFXUtil.FloatToInt(y); Line_Internal(px, py, nx, ny, false); px = nx; py = ny; } }); } return; } for (double l = -1; l <= 1.0001; l += 2) { //2 arcs gives circle //TODO: make flatten circle in GeomUtil instead GeomUtil.FlattenArc(cx + radius * l, cy, cx - radius * l, cy, 1.0, true, flattentol, (x, y, moveto) => { if (moveto) { px = GFXUtil.FloatToInt(x); py = GFXUtil.FloatToInt(y); } else { nx = GFXUtil.FloatToInt(x); ny = GFXUtil.FloatToInt(y); Line_Internal(px, py, nx, ny, false); px = nx; py = ny; } }); } }