/// <summary> /// Draw specific border (top/bottom/left/right) with the box data (style/width/rounded).<br/> /// </summary> /// <param name="border">desired border to draw</param> /// <param name="box">the box to draw its borders, contain the borders data</param> /// <param name="g">the device to draw into</param> /// <param name="rect">the rectangle the border is enclosing</param> /// <param name="isLineStart">Specifies if the border is for a starting line (no bevel on left)</param> /// <param name="isLineEnd">Specifies if the border is for an ending line (no bevel on right)</param> private static void DrawBorder(Border border, CssBox box, RGraphics g, RRect rect, bool isLineStart, bool isLineEnd) { var style = GetStyle(border, box); var color = GetColor(border, box, style); var borderPath = GetRoundedBorderPath(g, border, box, rect); if (borderPath != null) { // rounded border need special path Object prevMode = null; if (box.HtmlContainer != null && !box.HtmlContainer.AvoidGeometryAntialias && box.IsRounded) prevMode = g.SetAntiAliasSmoothingMode(); var pen = GetPen(g, style, color, GetWidth(border, box)); using (borderPath) g.DrawPath(pen, borderPath); g.ReturnPreviousSmoothingMode(prevMode); } else { // non rounded border if (style == CssConstants.Inset || style == CssConstants.Outset) { // inset/outset border needs special rectangle SetInOutsetRectanglePoints(border, box, rect, isLineStart, isLineEnd); g.DrawPolygon(g.GetSolidBrush(color), _borderPts); } else { // solid/dotted/dashed border draw as simple line var pen = GetPen(g, style, color, GetWidth(border, box)); switch (border) { case Border.Top: g.DrawLine(pen, Math.Ceiling(rect.Left), rect.Top + box.ActualBorderTopWidth / 2, rect.Right - 1, rect.Top + box.ActualBorderTopWidth / 2); break; case Border.Left: g.DrawLine(pen, rect.Left + box.ActualBorderLeftWidth / 2, Math.Ceiling(rect.Top), rect.Left + box.ActualBorderLeftWidth / 2, Math.Floor(rect.Bottom)); break; case Border.Bottom: g.DrawLine(pen, Math.Ceiling(rect.Left), rect.Bottom - box.ActualBorderBottomWidth / 2, rect.Right - 1, rect.Bottom - box.ActualBorderBottomWidth / 2); break; case Border.Right: g.DrawLine(pen, rect.Right - box.ActualBorderRightWidth / 2, Math.Ceiling(rect.Top), rect.Right - box.ActualBorderRightWidth / 2, Math.Floor(rect.Bottom)); break; } } } }
/// <summary> /// Paints the text decoration (underline/strike-through/over-line) /// </summary> /// <param name="g">the device to draw into</param> /// <param name="rectangle"> </param> /// <param name="isFirst"> </param> /// <param name="isLast"> </param> protected void PaintDecoration(RGraphics g, RRect rectangle, bool isFirst, bool isLast) { if (string.IsNullOrEmpty(TextDecoration) || TextDecoration == CssConstants.None) return; double y = 0f; if (TextDecoration == CssConstants.Underline) { y = Math.Round(rectangle.Top + ActualFont.UnderlineOffset); } else if (TextDecoration == CssConstants.LineThrough) { y = rectangle.Top + rectangle.Height / 2f; } else if (TextDecoration == CssConstants.Overline) { y = rectangle.Top; } y -= ActualPaddingBottom - ActualBorderBottomWidth; double x1 = rectangle.X; if (isFirst) x1 += ActualPaddingLeft + ActualBorderLeftWidth; double x2 = rectangle.Right; if (isLast) x2 -= ActualPaddingRight + ActualBorderRightWidth; var pen = g.GetPen(ActualColor); pen.Width = 1; pen.DashStyle = RDashStyle.Solid; g.DrawLine(pen, x1, y, x2, y); }