private static void DrawString(PageText pt, Graphics g, RectangleF r, CanvasProperties cp, PageItemManager cpim) { StyleInfo si = pt.SI; string s = pt.Text; Font drawFont = null; StringFormat drawFormat = null; Brush drawBrush = null; try { // STYLE System.Drawing.FontStyle fs = 0; if (si.FontStyle == FontStyleEnum.Italic) { fs |= System.Drawing.FontStyle.Italic; } switch (si.TextDecoration) { case TextDecorationEnum.Underline: fs |= System.Drawing.FontStyle.Underline; break; case TextDecorationEnum.LineThrough: fs |= System.Drawing.FontStyle.Strikeout; break; case TextDecorationEnum.Overline: case TextDecorationEnum.None: break; } // WEIGHT switch (si.FontWeight) { case FontWeightEnum.Bold: case FontWeightEnum.Bolder: case FontWeightEnum.W500: case FontWeightEnum.W600: case FontWeightEnum.W700: case FontWeightEnum.W800: case FontWeightEnum.W900: fs |= System.Drawing.FontStyle.Bold; break; default: break; } try { drawFont = new Font(si.GetFontFamily(), si.FontSize, fs); // si.FontSize already in points } catch (ArgumentException) { drawFont = new Font("Arial", si.FontSize, fs); // if this fails we'll let the error pass thru } // ALIGNMENT drawFormat = new StringFormat(); switch (si.TextAlign) { case TextAlignEnum.Right: drawFormat.Alignment = StringAlignment.Far; break; case TextAlignEnum.Center: drawFormat.Alignment = StringAlignment.Center; break; case TextAlignEnum.Left: default: drawFormat.Alignment = StringAlignment.Near; break; } if (pt.SI.WritingMode == WritingModeEnum.tb_rl) { drawFormat.FormatFlags |= StringFormatFlags.DirectionRightToLeft; drawFormat.FormatFlags |= StringFormatFlags.DirectionVertical; } switch (si.VerticalAlign) { case VerticalAlignEnum.Bottom: drawFormat.LineAlignment = StringAlignment.Far; break; case VerticalAlignEnum.Middle: drawFormat.LineAlignment = StringAlignment.Center; break; case VerticalAlignEnum.Top: default: drawFormat.LineAlignment = StringAlignment.Near; break; } // draw the background DrawBackground(g, r, si); // adjust drawing rectangle based on padding //RectangleF r2 = new RectangleF(r.Left + si.PaddingLeft, // r.Top + si.PaddingTop, // r.Width - si.PaddingLeft - si.PaddingRight, // r.Height - si.PaddingTop - si.PaddingBottom); // http://www.fyireporting.com/forum/viewtopic.php?t=892 //A.S.> convert pt to px if needed(when printing we need px, when draw preview - pt) RectangleF r2; if (g.PageUnit == GraphicsUnit.Pixel) { r2 = new RectangleF(r.Left + (si.PaddingLeft * g.DpiX) / 72, r.Top + (si.PaddingTop * g.DpiX) / 72, r.Width - ((si.PaddingLeft + si.PaddingRight) * g.DpiX) / 72, r.Height - ((si.PaddingTop + si.PaddingBottom) * g.DpiX) / 72); } else { // adjust drawing rectangle based on padding r2 = new RectangleF(r.Left + si.PaddingLeft, r.Top + si.PaddingTop, r.Width - si.PaddingLeft - si.PaddingRight, r.Height - si.PaddingTop - si.PaddingBottom); } drawBrush = new SolidBrush(si.Color); if (si.TextAlign == TextAlignEnum.Justified) //Added from forum: Hugo http://www.fyireporting.com/forum/viewtopic.php?t=552 { GraphicsExtended.DrawStringJustified(g, pt.Text, drawFont, drawBrush, r2, '-'); } else if (pt.NoClip) // request not to clip text { g.DrawString(pt.Text, drawFont, drawBrush, new PointF(r.Left, r.Top), drawFormat); HighlightString(g, pt, new RectangleF(r.Left, r.Top, float.MaxValue, float.MaxValue), drawFont, drawFormat, cp); } else { g.DrawString(pt.Text, drawFont, drawBrush, r2, drawFormat); HighlightString(g, pt, r2, drawFont, drawFormat, cp); } if (cpim.SelectToolEnabled) { if (pt.AllowSelect && cpim.SelectedItemList.Contains(pt)) { g.FillRectangle(new SolidBrush(Color.FromArgb(50, cp.SelectItemColor)), r2); } } } finally { if (drawFont != null) { drawFont.Dispose(); } if (drawFormat != null) { drawFont.Dispose(); } if (drawBrush != null) { drawBrush.Dispose(); } } }
/// <summary> /// A draw accounting for scrolling and zoom factors. /// </summary> public static void Draw(Graphics g, Pages pages, float pageGap, Rectangle clipRectangle, ref CanvasProperties cp, ref PageItemManager cpim) { if (pages == null) { // No pages; means nothing to draw g.FillRectangle(Brushes.White, clipRectangle); return; } g.PageUnit = GraphicsUnit.Pixel; g.ScaleTransform(cp.Zoom, cp.Zoom); cp.Dpi = new PointF(g.DpiX, g.DpiY); // Zoom affects how much will show on the screen. Adjust our perceived clipping rectangle // to account for it. RectangleF r; r = new RectangleF((clipRectangle.X) / cp.Zoom, (clipRectangle.Y) / cp.Zoom, (clipRectangle.Width) / cp.Zoom, (clipRectangle.Height) / cp.Zoom); // Calculate the top of the page int fpage = (int)(cp.Scroll.Y / Measurement.PixelsFromPoints(pages.PageHeight + pageGap, cp.Dpi.Y)); int lpage = (int)((cp.Scroll.Y + r.Height) / Measurement.PixelsFromPoints(pages.PageHeight + pageGap, cp.Dpi.X)) + 1; if (fpage >= pages.PageCount) { return; } if (lpage >= pages.PageCount) { lpage = pages.PageCount - 1; } cp.Left = cp.Offset.X; cp.Top = pageGap; // Loop thru the visible pages for (int p = fpage; p <= lpage; p++) { cp.Scroll = new PointF( cp.Scroll.X, (cp.Scroll.Y - Measurement.PixelsFromPoints(p * (pages.PageHeight + pageGap), cp.Dpi.Y)) ); System.Drawing.Rectangle pr = new System.Drawing.Rectangle( (int)(Measurement.PixelsFromPoints(cp.Left, cp.Dpi.X) - cp.Scroll.X), (int)(Measurement.PixelsFromPoints(cp.Top, cp.Dpi.Y) - cp.Scroll.Y), (int)Measurement.PixelsFromPoints(pages.PageWidth, cp.Dpi.X), (int)Measurement.PixelsFromPoints(pages.PageHeight, cp.Dpi.Y)); g.FillRectangle(Brushes.White, pr); ProcessPage(g, pages[p], r, true, cp, ref cpim); // Draw the page outline using (Pen pn = new Pen(Brushes.Black, 1)) { int z3 = Math.Min((int)(3f / cp.Zoom), 3); if (z3 <= 0) { z3 = 1; } int z4 = Math.Min((int)(4f / cp.Zoom), 4); if (z4 <= 0) { z4 = 1; } g.DrawRectangle(pn, pr); // outline of page g.FillRectangle(Brushes.Black, pr.X + pr.Width, pr.Y + z3, z3, pr.Height); // right side of page g.FillRectangle(Brushes.Black, pr.X + z3, pr.Y + pr.Height, pr.Width, z4); // bottom of page } } }
private static void DrawImageSized(PageImage pi, Image im, Graphics g, RectangleF r, CanvasProperties cp, PageItemManager cpim) { float height, width; // some work variables StyleInfo si = pi.SI; // adjust drawing rectangle based on padding //RectangleF r2 = new RectangleF(r.Left + PixelsX(si.PaddingLeft), // r.Top + PixelsY(si.PaddingTop), // r.Width - PixelsX(si.PaddingLeft + si.PaddingRight), // r.Height - PixelsY(si.PaddingTop + si.PaddingBottom)); // http://www.fyireporting.com/forum/viewtopic.php?t=892 //A.S.> convert pt to px if needed(when printing we need px, when draw preview - pt) RectangleF r2; if (g.PageUnit == GraphicsUnit.Pixel) { r2 = new RectangleF(r.Left + (si.PaddingLeft * g.DpiX) / 72, r.Top + (si.PaddingTop * g.DpiX) / 72, r.Width - ((si.PaddingLeft + si.PaddingRight) * g.DpiX) / 72, r.Height - ((si.PaddingTop + si.PaddingBottom) * g.DpiX) / 72); } else { // adjust drawing rectangle based on padding r2 = new RectangleF(r.Left + si.PaddingLeft, r.Top + si.PaddingTop, r.Width - si.PaddingLeft - si.PaddingRight, r.Height - si.PaddingTop - si.PaddingBottom); } Rectangle ir; // int work rectangle ir = new Rectangle(Convert.ToInt32(r2.Left), Convert.ToInt32(r2.Top), Convert.ToInt32(r2.Width), Convert.ToInt32(r2.Height)); switch (pi.Sizing) { case ImageSizingEnum.AutoSize: // Note: GDI+ will stretch an image when you only provide // the left/top coordinates. This seems pretty stupid since // it results in the image being out of focus even though // you don't want the image resized. if (g.DpiX == im.HorizontalResolution && g.DpiY == im.VerticalResolution) { ir = new Rectangle(Convert.ToInt32(r2.Left), Convert.ToInt32(r2.Top), im.Width, im.Height); } g.DrawImage(im, ir); break; case ImageSizingEnum.Clip: Region saveRegion = g.Clip; Region clipRegion = new Region(g.Clip.GetRegionData()); clipRegion.Intersect(r2); g.Clip = clipRegion; if (g.DpiX == im.HorizontalResolution && g.DpiY == im.VerticalResolution) { ir = new Rectangle(Convert.ToInt32(r2.Left), Convert.ToInt32(r2.Top), im.Width, im.Height); } g.DrawImage(im, ir); g.Clip = saveRegion; break; case ImageSizingEnum.FitProportional: float ratioIm = (float)im.Height / (float)im.Width; float ratioR = r2.Height / r2.Width; height = r2.Height; width = r2.Width; if (ratioIm > ratioR) { // this means the rectangle width must be corrected width = height * (1 / ratioIm); } else if (ratioIm < ratioR) { // this means the ractangle height must be corrected height = width * ratioIm; } r2 = new RectangleF(r2.X, r2.Y, width, height); g.DrawImage(im, r2); break; case ImageSizingEnum.Fit: default: g.DrawImage(im, r2); break; } if (cpim.SelectToolEnabled && pi.AllowSelect && cpim.SelectedItemList.Contains(pi)) { g.FillRectangle(new SolidBrush(Color.FromArgb(50, cp.SelectItemColor)), ir); } return; }
/// <summary> /// A simple draw of an entire page. Useful when printing or creating an image. /// </summary> public static void Draw(Graphics g, int page, Pages pages, Rectangle clipRectangle, bool drawBackground, ref CanvasProperties cp, ref PageItemManager cpim) { cp.Dpi = new PointF(g.DpiX, g.DpiY); // this can change (e.g. printing graphics context) cp.HighlightText = null; cp.HighlightItem = null; cp.HighlightAll = false; cp.HighlightCaseSensitive = false; // g.InterpolationMode = InterpolationMode.HighQualityBilinear; // try to unfuzz charts g.PageUnit = GraphicsUnit.Pixel; g.ScaleTransform(1, 1); if (!cp.Offset.IsEmpty) // used when correcting for non-printable area on paper { g.TranslateTransform(cp.Offset.X, cp.Offset.Y); } cp.Left = 0; cp.Top = 0; cp.Scroll = new PointF(0, 0); RectangleF r = new RectangleF(clipRectangle.X, clipRectangle.Y, clipRectangle.Width, clipRectangle.Height); if (drawBackground) { g.FillRectangle( Brushes.White, Measurement.PixelsFromPoints(cp.Left, cp.Dpi.X), Measurement.PixelsFromPoints(cp.Top, cp.Dpi.Y), Measurement.PixelsFromPoints(pages.PageWidth, cp.Dpi.X), Measurement.PixelsFromPoints(pages.PageHeight, cp.Dpi.Y)); } ProcessPage(g, pages[page], r, false, cp, ref cpim); }
private static void DrawImage(PageImage pi, Graphics g, RectangleF r, CanvasProperties cp, PageItemManager cpim) { Stream strm = null; System.Drawing.Image im = null; try { strm = new MemoryStream(pi.ImageData); im = Image.FromStream(strm); DrawImageSized(pi, im, g, r, cp, cpim); } finally { if (strm != null) { strm.Close(); } if (im != null) { im.Dispose(); } } }
/// <summary> /// Pre-Processes the HTML prior to rendering it in a page. /// </summary> public static void ProcessHtml(PageTextHtml pth, Graphics g, RectangleF clipRect, bool bHitList, CanvasProperties cp, ref PageItemManager cpim) { pth.Build(g); // Builds the subobjects that make up the html CanvasPainter.ProcessPage(g, pth, clipRect, bHitList, cp, ref cpim); }
/// <summary> /// Renders all the objects in a Page or composite object. /// </summary> private static void ProcessPage(Graphics g, IEnumerable p, RectangleF clipRect, bool bHitList, CanvasProperties cp, ref PageItemManager cpim) { foreach (PageItem pi in p) { if (pi is PageTextHtml) { // PageTextHtml is actually a composite object (just like a page) if (cpim.SelectToolEnabled && bHitList) { RectangleF hr = new RectangleF( Measurement.PixelsFromPoints(pi.X + cp.Left - cp.Scroll.X, cp.Dpi.X), Measurement.PixelsFromPoints(pi.Y + cp.Scroll.X - cp.Scroll.Y, cp.Dpi.Y), Measurement.PixelsFromPoints(pi.W, cp.Dpi.X), Measurement.PixelsFromPoints(pi.H, cp.Dpi.Y)); cpim.HitList.Add(new HitListEntry(hr, pi)); } ProcessHtml(pi as PageTextHtml, g, clipRect, bHitList, cp, ref cpim); continue; } if (pi is PageLine) { PageLine pl = pi as PageLine; CanvasPainter.DrawLine( pl.SI.BColorLeft, pl.SI.BStyleLeft, pl.SI.BWidthLeft, g, Measurement.PixelsFromPoints(pl.X + cp.Left - cp.Scroll.X, cp.Dpi.X), Measurement.PixelsFromPoints(pl.Y + cp.Top - cp.Scroll.Y, cp.Dpi.Y), Measurement.PixelsFromPoints(pl.X2 + cp.Left - cp.Scroll.X, cp.Dpi.X), Measurement.PixelsFromPoints(pl.Y2 + cp.Top - cp.Scroll.Y, cp.Dpi.Y)); continue; } RectangleF rect = new RectangleF( Measurement.PixelsFromPoints(pi.X + cp.Left - cp.Scroll.X, cp.Dpi.X), Measurement.PixelsFromPoints(pi.Y + cp.Top - cp.Scroll.Y, cp.Dpi.Y), Measurement.PixelsFromPoints(pi.W, cp.Dpi.X), Measurement.PixelsFromPoints(pi.H, cp.Dpi.Y)); // Maintain the hit list if (bHitList) { if (cpim.SelectToolEnabled) { // we need all PageText and PageImage items that have been displayed if (pi is PageText || pi is PageImage) { cpim.HitList.Add(new HitListEntry(rect, pi)); } } // Only care about items with links and tips else if (pi.HyperLink != null || pi.BookmarkLink != null || pi.Tooltip != null) { HitListEntry hle; if (pi is PagePolygon) { hle = new HitListEntry(pi as PagePolygon, cp.Left - cp.Scroll.X, cp.Top - cp.Scroll.Y, ((Canvas)cp.Parent)); } else { hle = new HitListEntry(rect, pi); } cpim.HitList.Add(hle); } } if ((pi is PagePolygon) || (pi is PageCurve)) { // intentionally empty; polygon's rectangles aren't calculated } else if (!rect.IntersectsWith(clipRect)) { continue; } if (pi.SI.BackgroundImage != null) { // put out any background image PageImage i = pi.SI.BackgroundImage; CanvasPainter.DrawImageBackground(i, pi.SI, g, rect); } if (pi is PageText) { PageText pt = pi as PageText; CanvasPainter.DrawString(pt, g, rect, cp, cpim); } else if (pi is PageImage) { PageImage i = pi as PageImage; CanvasPainter.DrawImage(i, g, rect, cp, cpim); } else if (pi is PageRectangle) { CanvasPainter.DrawBackground(g, rect, pi.SI); } else if (pi is PageEllipse) { PageEllipse pe = pi as PageEllipse; CanvasPainter.DrawEllipse(pe, g, rect); } else if (pi is PagePie) { PagePie pp = pi as PagePie; CanvasPainter.DrawPie(pp, g, rect); } else if (pi is PagePolygon) { PagePolygon ppo = pi as PagePolygon; CanvasPainter.FillPolygon(ppo, g, rect, cp); } else if (pi is PageCurve) { PageCurve pc = pi as PageCurve; CanvasPainter.DrawCurve(pc.SI.BColorLeft, pc.SI.BStyleLeft, pc.SI.BWidthLeft, g, pc.Points, pc.Offset, pc.Tension, cp); } CanvasPainter.DrawBorder(pi, g, rect); } }