/// <summary> /// Clip the region the graphics will draw on by the overflow style of the containing block.<br/> /// Recursively travel up the tree to find containing block that has overflow style set to hidden. if not /// block found there will be no clipping and null will be returned. /// </summary> /// <param name="g">the graphics to clip</param> /// <param name="box">the box that is rendered to get containing blocks</param> /// <returns>true - was clipped, false - not clipped</returns> public static bool ClipGraphicsByOverflow(RGraphics g, CssBox box) { var containingBlock = box.ContainingBlock; while (true) { if (containingBlock.Overflow == CssConstants.Hidden) { var prevClip = g.GetClip(); var rect = box.ContainingBlock.ClientRectangle; rect.X -= 2; // TODO:a find better way to fix it rect.Width += 2; rect.Offset(box.HtmlContainer.ScrollOffset); rect.Intersect(prevClip); g.PushClip(rect); return(true); } var cBlock = containingBlock.ContainingBlock; if (cBlock == containingBlock) { return(false); } containingBlock = cBlock; } }
/// <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) { // 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); 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); switch (box.BackgroundRepeat) { case "no-repeat": g.DrawImage(imageLoadHandler.Image, destRect, srcRect); break; case "repeat-x": DrawRepeatX(g, imageLoadHandler, rectangle, srcRect, destRect, imgSize); break; case "repeat-y": DrawRepeatY(g, imageLoadHandler, rectangle, srcRect, destRect, imgSize); break; default: DrawRepeat(g, imageLoadHandler, rectangle, srcRect, destRect, imgSize); break; } g.PopClip(); }
/// <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(); }