/// <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> /// Draw the background image of the given box in the given rectangle.<br/> /// Handle background-repeat and background-position values. /// </summary> /// <param name="g">the device to draw into</param> /// <param name="box">the box to draw its background image</param> /// <param name="imageLoadHandler">the handler that loads image to draw</param> /// <param name="rectangle">the rectangle to draw image in</param> public static void DrawBackgroundImage(RGraphics g, CssBox box, ImageLoadHandler imageLoadHandler, RRect rectangle, RGraphicsPath roundrect = null) { // image size depends if specific rectangle given in image loader var imgSize = new RSize(imageLoadHandler.Rectangle == RRect.Empty ? imageLoadHandler.Image.Width : imageLoadHandler.Rectangle.Width, imageLoadHandler.Rectangle == RRect.Empty ? imageLoadHandler.Image.Height : imageLoadHandler.Rectangle.Height); // get the location by BackgroundPosition value var location = GetLocation(box.BackgroundPosition, rectangle, imgSize, box); var srcRect = imageLoadHandler.Rectangle == RRect.Empty ? new RRect(0, 0, imgSize.Width, imgSize.Height) : new RRect(imageLoadHandler.Rectangle.Left, imageLoadHandler.Rectangle.Top, imgSize.Width, imgSize.Height); // initial image destination rectangle var destRect = new RRect(location, imgSize); // need to clip so repeated image will be cut on rectangle var lRectangle = rectangle; lRectangle.Intersect(g.GetClip()); g.PushClip(lRectangle); //rectangle - box to draw in //imgSize - image size //localion - inital location of image wo repeat //destRect - RRect(location, imgSize) //srcRect (0,0,imgSize) //brushRect - This is rectangle which needs to be filled with Image from brushRect.Location with brushRect.Size multiple to Image size. RRect brushRect = new RRect(location, imgSize); switch (box.BackgroundRepeat) { case "no-repeat": //brushRect = destRect; break; case "repeat-x": if (brushRect.X > rectangle.X) { brushRect.X -= imgSize.Width * ((int)((brushRect.X - rectangle.X) / imgSize.Width) + 1); } if (brushRect.X + brushRect.Width < rectangle.X + rectangle.Width) { brushRect.Width = imgSize.Width * ((int)((rectangle.X + rectangle.Width - brushRect.X) / imgSize.Width) + 1); } break; case "repeat-y": if (brushRect.Y > rectangle.Y) { brushRect.Y -= imgSize.Height * ((int)((brushRect.Y - rectangle.Y) / imgSize.Height) + 1); } if (brushRect.Y + brushRect.Height < rectangle.Y + rectangle.Height) { brushRect.Height = imgSize.Height * ((int)((rectangle.Y + rectangle.Height - brushRect.Y) / imgSize.Height) + 1); } break; default: if (brushRect.X > rectangle.X) { brushRect.X -= imgSize.Width * ((int)((brushRect.X - rectangle.X) / imgSize.Width) + 1); } if (brushRect.X + brushRect.Width < rectangle.X + rectangle.Width) { brushRect.Width = imgSize.Width * ((int)((rectangle.X + rectangle.Width - brushRect.X) / imgSize.Width) + 1); } if (brushRect.Y > rectangle.Y) { brushRect.Y -= imgSize.Height * ((int)((brushRect.Y - rectangle.Y) / imgSize.Height) + 1); } if (brushRect.Y + brushRect.Height < rectangle.Y + rectangle.Height) { brushRect.Height = imgSize.Height * ((int)((rectangle.Y + rectangle.Height - brushRect.Y) / imgSize.Height) + 1); } break; } using (var brush = g.GetTextureBrush(imageLoadHandler.Image, brushRect, brushRect.Location)) { if (roundrect == null) { g.DrawRectangle(brush, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); } else { g.DrawPath(brush, roundrect); } } g.PopClip(); }