/// <summary> /// Makes a border path for rounded borders.<br/> /// To support rounded dotted/dashed borders we need to use arc in the border path.<br/> /// Return null if the border is not rounded.<br/> /// </summary> /// <param name="g">the device to draw into</param> /// <param name="border">Desired border</param> /// <param name="b">Box which the border corresponds</param> /// <param name="r">the rectangle the border is enclosing</param> /// <returns>Beveled border path, null if there is no rounded corners</returns> private static RGraphicsPath GetRoundedBorderPath(RGraphics g, Border border, CssBox b, RRect r) { RGraphicsPath path = null; switch (border) { case Border.Top: if (b.ActualCornerNw > 0 || b.ActualCornerNe > 0) { path = g.GetGraphicsPath(); path.Start(r.Left + b.ActualBorderLeftWidth / 2, r.Top + b.ActualBorderTopWidth / 2 + b.ActualCornerNw); if (b.ActualCornerNw > 0) path.ArcTo(r.Left + b.ActualBorderLeftWidth / 2 + b.ActualCornerNw, r.Top + b.ActualBorderTopWidth / 2, b.ActualCornerNw, RGraphicsPath.Corner.TopLeft); path.LineTo(r.Right - b.ActualBorderRightWidth / 2 - b.ActualCornerNe, r.Top + b.ActualBorderTopWidth / 2); if (b.ActualCornerNe > 0) path.ArcTo(r.Right - b.ActualBorderRightWidth / 2, r.Top + b.ActualBorderTopWidth / 2 + b.ActualCornerNe, b.ActualCornerNe, RGraphicsPath.Corner.TopRight); } break; case Border.Bottom: if (b.ActualCornerSw > 0 || b.ActualCornerSe > 0) { path = g.GetGraphicsPath(); path.Start(r.Right - b.ActualBorderRightWidth / 2, r.Bottom - b.ActualBorderBottomWidth / 2 - b.ActualCornerSe); if (b.ActualCornerSe > 0) path.ArcTo(r.Right - b.ActualBorderRightWidth / 2 - b.ActualCornerSe, r.Bottom - b.ActualBorderBottomWidth / 2, b.ActualCornerSe, RGraphicsPath.Corner.BottomRight); path.LineTo(r.Left + b.ActualBorderLeftWidth / 2 + b.ActualCornerSw, r.Bottom - b.ActualBorderBottomWidth / 2); if (b.ActualCornerSw > 0) path.ArcTo(r.Left + b.ActualBorderLeftWidth / 2, r.Bottom - b.ActualBorderBottomWidth / 2 - b.ActualCornerSw, b.ActualCornerSw, RGraphicsPath.Corner.BottomLeft); } break; case Border.Right: if (b.ActualCornerNe > 0 || b.ActualCornerSe > 0) { path = g.GetGraphicsPath(); bool noTop = b.BorderTopStyle == CssConstants.None || b.BorderTopStyle == CssConstants.Hidden; bool noBottom = b.BorderBottomStyle == CssConstants.None || b.BorderBottomStyle == CssConstants.Hidden; path.Start(r.Right - b.ActualBorderRightWidth / 2 - (noTop ? b.ActualCornerNe : 0), r.Top + b.ActualBorderTopWidth / 2 + (noTop ? 0 : b.ActualCornerNe)); if (b.ActualCornerNe > 0 && noTop) path.ArcTo(r.Right - b.ActualBorderLeftWidth / 2, r.Top + b.ActualBorderTopWidth / 2 + b.ActualCornerNe, b.ActualCornerNe, RGraphicsPath.Corner.TopRight); path.LineTo(r.Right - b.ActualBorderRightWidth / 2, r.Bottom - b.ActualBorderBottomWidth / 2 - b.ActualCornerSe); if (b.ActualCornerSe > 0 && noBottom) path.ArcTo(r.Right - b.ActualBorderRightWidth / 2 - b.ActualCornerSe, r.Bottom - b.ActualBorderBottomWidth / 2, b.ActualCornerSe, RGraphicsPath.Corner.BottomRight); } break; case Border.Left: if (b.ActualCornerNw > 0 || b.ActualCornerSw > 0) { path = g.GetGraphicsPath(); bool noTop = b.BorderTopStyle == CssConstants.None || b.BorderTopStyle == CssConstants.Hidden; bool noBottom = b.BorderBottomStyle == CssConstants.None || b.BorderBottomStyle == CssConstants.Hidden; path.Start(r.Left + b.ActualBorderLeftWidth / 2 + (noBottom ? b.ActualCornerSw : 0), r.Bottom - b.ActualBorderBottomWidth / 2 - (noBottom ? 0 : b.ActualCornerSw)); if (b.ActualCornerSw > 0 && noBottom) path.ArcTo(r.Left + b.ActualBorderLeftWidth / 2, r.Bottom - b.ActualBorderBottomWidth / 2 - b.ActualCornerSw, b.ActualCornerSw, RGraphicsPath.Corner.BottomLeft); path.LineTo(r.Left + b.ActualBorderLeftWidth / 2, r.Top + b.ActualBorderTopWidth / 2 + b.ActualCornerNw); if (b.ActualCornerNw > 0 && noTop) path.ArcTo(r.Left + b.ActualBorderLeftWidth / 2 + b.ActualCornerNw, r.Top + b.ActualBorderTopWidth / 2, b.ActualCornerNw, RGraphicsPath.Corner.TopLeft); } break; } return path; }
/// <summary> /// Creates a rounded rectangle using the specified corner radius<br/> /// NW-----NE /// | | /// | | /// SW-----SE /// </summary> /// <param name="g">the device to draw into</param> /// <param name="rect">Rectangle to round</param> /// <param name="nwRadius">Radius of the north east corner</param> /// <param name="neRadius">Radius of the north west corner</param> /// <param name="seRadius">Radius of the south east corner</param> /// <param name="swRadius">Radius of the south west corner</param> /// <returns>GraphicsPath with the lines of the rounded rectangle ready to be painted</returns> public static RGraphicsPath GetRoundRect(RGraphics g, RRect rect, double nwRadius, double neRadius, double seRadius, double swRadius) { var path = g.GetGraphicsPath(); path.Start(rect.Left + nwRadius, rect.Top); path.LineTo(rect.Right - neRadius, rect.Y); if (neRadius > 0f) path.ArcTo(rect.Right, rect.Top + neRadius, neRadius, RGraphicsPath.Corner.TopRight); path.LineTo(rect.Right, rect.Bottom - seRadius); if (seRadius > 0f) path.ArcTo(rect.Right - seRadius, rect.Bottom, seRadius, RGraphicsPath.Corner.BottomRight); path.LineTo(rect.Left + swRadius, rect.Bottom); if (swRadius > 0f) path.ArcTo(rect.Left, rect.Bottom - swRadius, swRadius, RGraphicsPath.Corner.BottomLeft); path.LineTo(rect.Left, rect.Top + nwRadius); if (nwRadius > 0f) path.ArcTo(rect.Left + nwRadius, rect.Top, nwRadius, RGraphicsPath.Corner.TopLeft); return path; }