/// <summary> /// Demonstrates the use of XGraphics.Transform. /// </summary> public override void RenderPage(XGraphics gfx) { base.RenderPage(gfx); //XGraphicsState state = gfx.Save(); gfx.Save(); gfx.IntersectClip(new XRect(20, 20, 300, 500)); gfx.DrawRectangle(XBrushes.Yellow, 0, 0, gfx.PageSize.Width, gfx.PageSize.Height); gfx.Restore(); gfx.Save(); gfx.IntersectClip(new XRect(100, 200, 300, 500)); gfx.DrawRectangle(XBrushes.LightBlue, 0, 0, gfx.PageSize.Width, gfx.PageSize.Height); gfx.DrawLine(XPens.MediumSlateBlue, 0, 0, 150, 200); gfx.DrawPolygon(properties.Pen1.Pen, GetPentagram(75, new PointF(150, 200))); Matrix matrix = new Matrix(); //matrix.Scale(2f, 1.5f); //matrix.Translate(-200, -400); //matrix.Rotate(45); //matrix.Translate(200, 400); //gfx.Transform = matrix; //gfx.TranslateTransform(50, 30); #if true gfx.TranslateTransform(30, 40, XMatrixOrder.Prepend); gfx.ScaleTransform(2.0f, 2.0f, XMatrixOrder.Prepend); gfx.RotateTransform(15, XMatrixOrder.Prepend); #else gfx.TranslateTransform(30, 40, XMatrixOrder.Append); gfx.ScaleTransform(2.0f, 2.0f, XMatrixOrder.Append); gfx.RotateTransform(15, XMatrixOrder.Append); #endif bool id = matrix.IsIdentity; matrix.Scale(2.0f, 2.0f, MatrixOrder.Prepend); //matrix.Translate(30, -50); matrix.Rotate(15, MatrixOrder.Prepend); //Matrix mtx = gfx.Transform.ToGdiMatrix(); //gfx.Transform = matrix; gfx.DrawLine(XPens.MediumSlateBlue, 0, 0, 150, 200); gfx.DrawPolygon(properties.Pen2.Pen, GetPentagram(75, new PointF(150, 200))); gfx.Restore(); gfx.DrawLine(XPens.Red, 0, 0, 1000, 1000); gfx.DrawPolygon(XPens.SandyBrown, GetPentagram(75, new PointF(150, 200))); }
void Box(XGraphics gfx, XRect rect, double startAngle, double sweepAngle) { double xc = rect.X + rect.Width / 2; double yc = rect.Y + rect.Height / 2; double a = startAngle * 0.0174532925199433; double b = (startAngle + sweepAngle) * 0.0174532925199433; XGraphicsState state = gfx.Save(); gfx.IntersectClip(rect); #if true #if true_ for (double deg = 0; deg < 360; deg += 10) gfx.DrawLine(XPens.Yellow, xc, yc, (xc + rect.Width / 2 * Math.Cos(deg * 0.0174532925199433)), (yc + rect.Height / 2 * Math.Sin(deg * 0.0174532925199433))); #endif double f = Math.Max(rect.Width / 2, rect.Height / 2); for (double deg = 0; deg < 360; deg += 10) gfx.DrawLine(XPens.Goldenrod, xc, yc, (xc + f * Math.Cos(deg * 0.0174532925199433)), (yc + f * Math.Sin(deg * 0.0174532925199433))); gfx.DrawLine(XPens.PaleGreen, xc, rect.Y, xc, rect.Y + rect.Height); gfx.DrawLine(XPens.PaleGreen, rect.X, yc, rect.X + rect.Width, yc); //gfx.DrawLine(XPens.DarkGray, xc, yc, (xc + rect.Width / 2 * Math.Cos(a)), (yc + rect.Height / 2 * Math.Sin(a))); //gfx.DrawLine(XPens.DarkGray, xc, yc, (xc + rect.Width / 2 * Math.Cos(b)), (yc + rect.Height / 2 * Math.Sin(b))); #endif gfx.Restore(state); gfx.DrawRectangle(properties.Pen1.Pen, rect); }
/// <summary> /// Demonstrates the use of XGraphics.SetClip. /// </summary> public override void RenderPage(XGraphics gfx) { base.RenderPage(gfx); gfx.Save(); gfx.TranslateTransform(50, 50); gfx.IntersectClip(new Rectangle(0, 0, 400, 250)); gfx.TranslateTransform(50, 50); //gfx.Clear(XColor.GhostWhite); gfx.DrawEllipse(XPens.Green, XBrushes.Yellow, 40, 40, 500, 500); gfx.Restore(); gfx.Save(); //gfx.Transform = new XMatrix(); //XMatrix.Identity; gfx.TranslateTransform(200, 200); gfx.IntersectClip(new Rectangle(0, 0, 400, 250)); gfx.DrawEllipse(XPens.Green, XBrushes.Yellow, 40, 40, 500, 500); gfx.Restore(); }
void RenderClipPath(XGraphics gfx) { gfx.TranslateTransform(15, 20); XGraphicsPath path = new XGraphicsPath(); path.AddString("Clip!", new XFontFamily("Verdana"), XFontStyle.Bold, 90, new XRect(0, 0, 250, 140), XStringFormats.Center); gfx.IntersectClip(path); gfx.DrawRectangle(XBrushes.LightSalmon, new XRect(0, 0, 10000, 10000)); // Draw a beam of dotted lines XPen pen = XPens.DarkRed.Clone(); pen.DashStyle = XDashStyle.Dot; for (double r = 0; r <= 90; r += 0.5) gfx.DrawLine(pen, 0, 0, 1000 * Math.Cos(r / 90 * Math.PI), 1000 * Math.Sin(r / 90 * Math.PI)); }
/// <summary> /// Draw the texture image in the given graphics at the given location. /// </summary> public void DrawRectangle(XGraphics g, double x, double y, double width, double height) { var prevState = g.Save(); g.IntersectClip(new XRect(x, y, width, height)); double rx = _translateTransformLocation.X; double w = _image.PixelWidth, h = _image.PixelHeight; while (rx < x + width) { double ry = _translateTransformLocation.Y; while (ry < y + height) { g.DrawImage(_image, rx, ry, w, h); ry += h; } rx += w; } g.Restore(prevState); }
public override void RenderPage(XGraphics gfx) { base.RenderPage(gfx); // Create a new graphical path XGraphicsPath path = new XGraphicsPath(); // Add the outline of the glyphs of the word 'Clip' to the path path.AddString("Clip!", new XFontFamily("Times New Roman"), XFontStyle.BoldItalic, 250, new XPoint(30, 100), XStringFormats.Default); #if DEBUG_ gfx.WriteComment("SetClip"); #endif // Set the path as clip path gfx.IntersectClip(path); #if DEBUG_ gfx.WriteComment("Random lines"); #endif // Draw some random lines to show that clipping happens Random rnd = new Random(42); for (int idx = 0; idx < 300; idx++) gfx.DrawLine(properties.Pen2.Pen, rnd.Next(600), rnd.Next(500), rnd.Next(600), rnd.Next(500)); }
/// <summary> /// Draw a multi-line string as it would be drawn by GDI+. /// Compensates for issues and draw-vs-PDF differences in PDFsharp. /// </summary> /// <param name="graphics">The graphics with which to draw.</param> /// <param name="text">The text to draw, which may contain line breaks.</param> /// <param name="font">The font with which to draw.</param> /// <param name="brush">The brush with which to draw.</param> /// <param name="pos">The position at which to draw.</param> /// <param name="size">The size to which to limit the drawn text; or Vector.Zero for no limit.</param> /// <param name="format">The string format to use.</param> /// <remarks> /// PDFsharp cannot currently render multi-line text to PDF files; it comes out as single line. /// This method simulates standard Graphics.DrawString() over PDFsharp. /// It always has the effect of StringFormatFlags.LineLimit (which PDFsharp does not support). /// </remarks> public void Draw(XGraphics graphics, Font font, Brush brush, Vector pos, Vector size, XStringFormat format) { // do a quick test to see if text is going to get drawn at the same size as last time; // if so, assume we don't need to recompute our layout for that reason. var sizeChecker = graphics.MeasureString("M q", font); if (sizeChecker != m_sizeChecker || pos != m_pos || m_size != size || m_requestedFormat.Alignment != format.Alignment || m_requestedFormat.LineAlignment != format.LineAlignment || m_requestedFormat.FormatFlags != format.FormatFlags) { m_invalidLayout = true; } m_sizeChecker = sizeChecker; if (m_invalidLayout) { // something vital has changed; rebuild our cached layout data RebuildCachedLayout(graphics, font, ref pos, ref size, format); m_invalidLayout = false; } var state = graphics.Save(); if (size != Vector.Zero) { graphics.IntersectClip(new RectangleF(pos.X, pos.Y, size.X, size.Y)); } // disable smoothing whilst rendering text; // visually this is no different, but is faster var smoothingMode = graphics.SmoothingMode; graphics.SmoothingMode = XSmoothingMode.HighSpeed; var origin = m_origin; for (var index=0; index<m_lines.Count; ++index) { if (size.Y > 0 && size.Y < m_lineHeight) break; // not enough remaining vertical space for a whole line var line = m_lines[index]; graphics.DrawString(line, font, brush, origin.X, origin.Y, m_actualFormat); origin += m_delta; size.Y -= m_lineHeight; } graphics.SmoothingMode = smoothingMode; graphics.Restore(state); }
private static void RenderToGraphics(Render.RenderContext ctx, int rot, float translateX, float translateY, XGraphics graphics) { graphics.TranslateTransform(translateX, translateY); graphics.RotateTransform(rot * 90); using (Maps.Rendering.RenderUtil.SaveState(graphics)) { if (ctx.clipPath != null) { XMatrix m = ctx.ImageSpaceToWorldSpace; graphics.MultiplyTransform(m); graphics.IntersectClip(ctx.clipPath); m.Invert(); graphics.MultiplyTransform(m); } ctx.graphics = graphics; Maps.Rendering.Render.RenderTile(ctx); } if (ctx.border && ctx.clipPath != null) { using (Maps.Rendering.RenderUtil.SaveState(graphics)) { // Render border in world space XMatrix m = ctx.ImageSpaceToWorldSpace; graphics.MultiplyTransform(m); XPen pen = new XPen(ctx.styles.imageBorderColor, 0.2f); // PdfSharp can't ExcludeClip so we take advantage of the fact that we know // the path starts on the left edge and proceeds clockwise. We extend the // path with a counterclockwise border around it, then use that to exclude // the original path's region for rendering the border. ctx.clipPath.Flatten(); RectangleF bounds = PathUtil.Bounds(ctx.clipPath); bounds.Inflate(2 * (float)pen.Width, 2 * (float)pen.Width); List<byte> types = new List<byte>(ctx.clipPath.Internals.GdiPath.PathTypes); List<PointF> points = new List<PointF>(ctx.clipPath.Internals.GdiPath.PathPoints); PointF key = points[0]; points.Add(new PointF(bounds.Left, key.Y)); types.Add(1); points.Add(new PointF(bounds.Left, bounds.Bottom)); types.Add(1); points.Add(new PointF(bounds.Right, bounds.Bottom)); types.Add(1); points.Add(new PointF(bounds.Right, bounds.Top)); types.Add(1); points.Add(new PointF(bounds.Left, bounds.Top)); types.Add(1); points.Add(new PointF(bounds.Left, key.Y)); types.Add(1); points.Add(new PointF(key.X, key.Y)); types.Add(1); XGraphicsPath path = new XGraphicsPath(points.ToArray(), types.ToArray(), XFillMode.Winding); graphics.IntersectClip(path); graphics.DrawPath(pen, ctx.clipPath); } } }
/// <summary> /// Clips through path. /// </summary> void DrawClipPath(XGraphics gfx, int number) { BeginBox(gfx, number, "Clip through Path"); XGraphicsPath path = new XGraphicsPath(); path.AddString("Clip!", new XFontFamily("Verdana"), XFontStyle.Bold, 90, new XRect(0, 0, 250, 140), XStringFormats.Center); gfx.IntersectClip(path); // Draw a beam of dotted lines XPen pen = XPens.DarkRed.Clone(); pen.DashStyle = XDashStyle.Dot; for (double r = 0; r <= 90; r += 0.5) gfx.DrawLine(pen, 0, 0, 250 * Math.Cos(r / 90 * Math.PI), 250 * Math.Sin(r / 90 * Math.PI)); EndBox(gfx); }
public override void Draw(XGraphics graphics, Palette palette, DrawingContext context) { Random random = new Random(Name.GetHashCode()); var topLeft = InnerBounds.GetCorner(CompassPoint.NorthWest); var topRight = InnerBounds.GetCorner(CompassPoint.NorthEast); var bottomLeft = InnerBounds.GetCorner(CompassPoint.SouthWest); var bottomRight = InnerBounds.GetCorner(CompassPoint.SouthEast); var top = new LineSegment(topLeft, topRight); var right = new LineSegment(topRight, bottomRight); var bottom = new LineSegment(bottomRight, bottomLeft); var left = new LineSegment(bottomLeft, topLeft); context.LinesDrawn.Add(top); context.LinesDrawn.Add(right); context.LinesDrawn.Add(bottom); context.LinesDrawn.Add(left); var brush = context.Selected ? palette.BorderBrush : palette.FillBrush; if (!Settings.DebugDisableLineRendering) { var path = palette.Path(); Drawing.AddLine(path, top, random); Drawing.AddLine(path, right, random); Drawing.AddLine(path, bottom, random); Drawing.AddLine(path, left, random); graphics.DrawPath(brush, path); if (IsDark) { var state = graphics.Save(); graphics.IntersectClip(path); brush = context.Selected ? palette.FillBrush : palette.BorderBrush; graphics.DrawPolygon(brush, new PointF[] { topRight.ToPointF(), new PointF(topRight.X - Settings.DarknessStripeSize, topRight.Y), new PointF(topRight.X, topRight.Y + Settings.DarknessStripeSize) }, XFillMode.Alternate); graphics.Restore(state); } graphics.DrawPath(palette.BorderPen, path); } var font = Settings.LargeFont; brush = context.Selected ? palette.FillBrush : palette.LargeTextBrush; Rect textBounds = InnerBounds; textBounds.Inflate(-5, -5); if (textBounds.Width > 0 && textBounds.Height > 0) { m_name.Draw(graphics, font, brush, textBounds.Position, textBounds.Size, XStringFormats.Center); } var expandedBounds = InnerBounds; expandedBounds.Inflate(Settings.ObjectListOffsetFromRoom, Settings.ObjectListOffsetFromRoom); var drawnObjectList = false; font = Settings.SmallFont; brush = palette.SmallTextBrush; if (!string.IsNullOrEmpty(Objects)) { XStringFormat format = new XStringFormat(); Vector pos = expandedBounds.GetCorner(m_objectsPosition); if (!Drawing.SetAlignmentFromCardinalOrOrdinalDirection(format, m_objectsPosition)) { // object list appears inside the room below its name format.LineAlignment = XLineAlignment.Far; format.Alignment = XStringAlignment.Near; //format.Trimming = StringTrimming.EllipsisCharacter; //format.FormatFlags = StringFormatFlags.LineLimit; var height = InnerBounds.Height / 2 - font.Height / 2; var bounds = new Rect(InnerBounds.Left + Settings.ObjectListOffsetFromRoom, InnerBounds.Bottom - height, InnerBounds.Width - Settings.ObjectListOffsetFromRoom, height - Settings.ObjectListOffsetFromRoom); brush = context.Selected ? palette.FillBrush : brush; if (bounds.Width > 0 && bounds.Height > 0) { m_objects.Draw(graphics, font, brush, bounds.Position, bounds.Size, format); } drawnObjectList = true; } else if (m_objectsPosition == CompassPoint.North || m_objectsPosition == CompassPoint.South) { pos.X += Settings.ObjectListOffsetFromRoom; } if (!drawnObjectList) { m_objects.Draw(graphics, font, brush, pos, Vector.Zero, format); } } }
public void Render(XGraphics graphics) { this.graphics = graphics; solidBrush = new XSolidBrush(); pen = new XPen(XColor.Empty); List<Timer> timers = new List<Timer>(); using (var fonts = new FontCache(styles)) { #region resources lock (s_imageInitLock) { if (styles.showNebulaBackground && s_nebulaImage == null) s_nebulaImage = XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Nebula.png")); if (styles.showRiftOverlay && s_riftImage == null) s_riftImage = new ImageHolder(Image.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Rifts.png"))); if (styles.showGalaxyBackground && s_galaxyImage == null) { // TODO: Don't load both unless necessary s_galaxyImage = new ImageHolder(Image.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Galaxy.png"))); s_galaxyImageGray = new ImageHolder(Image.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Galaxy_Gray.png"))); } if (styles.useWorldImages && s_worldImages == null) { s_worldImages = new Dictionary<string, XImage> { { "Hyd0", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Hyd0.png")) }, { "Hyd1", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Hyd1.png")) }, { "Hyd2", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Hyd2.png")) }, { "Hyd3", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Hyd3.png")) }, { "Hyd4", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Hyd4.png")) }, { "Hyd5", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Hyd5.png")) }, { "Hyd6", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Hyd6.png")) }, { "Hyd7", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Hyd7.png")) }, { "Hyd8", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Hyd8.png")) }, { "Hyd9", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Hyd9.png")) }, { "HydA", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/HydA.png")) }, { "Belt", XImage.FromFile(resourceManager.Server.MapPath(@"~/res/Candy/Belt.png")) } }; } if (Silly && s_sillyImageColor == null) { // Happy face c/o http://bighappyfaces.com/ s_sillyImageColor = XImage.FromFile(resourceManager.Server.MapPath(@"~/res/AprilFools/Starburst.png")); s_sillyImageGray = XImage.FromFile(resourceManager.Server.MapPath(@"~/res/AprilFools/Starburst_Gray.png")); } } #endregion timers.Add(new Timer("preload")); ////////////////////////////////////////////////////////////// // // Image-Space Rendering // ////////////////////////////////////////////////////////////// using (RenderUtil.SaveState(graphics)) { if (ClipPath != null) { graphics.MultiplyTransform(imageSpaceToWorldSpace); graphics.IntersectClip(ClipPath); graphics.MultiplyTransform(worldSpaceToImageSpace); } // Fill graphics.SmoothingMode = XSmoothingMode.HighSpeed; solidBrush.Color = styles.backgroundColor; graphics.DrawRectangle(solidBrush, 0, 0, tileSize.Width, tileSize.Height); } timers.Add(new Timer("imagespace")); ////////////////////////////////////////////////////////////// // // World-Space Rendering // ////////////////////////////////////////////////////////////// graphics.MultiplyTransform(imageSpaceToWorldSpace); using (RenderUtil.SaveState(graphics)) { //------------------------------------------------------------ // Explicit Clipping //------------------------------------------------------------ if (ClipPath != null) graphics.IntersectClip(ClipPath); //------------------------------------------------------------ // Background //------------------------------------------------------------ timers.Add(new Timer("prep")); #region nebula-background //------------------------------------------------------------ // Local background (Nebula) //------------------------------------------------------------ // NOTE: Since alpha texture brushes aren't supported without // creating a new image (slow!) we render the local background // first, then overlay the deep background over it, for // basically the same effect since the alphas sum to 1. if (styles.showNebulaBackground) DrawNebulaBackground(); timers.Add(new Timer("background (nebula)")); #endregion #region galaxy-background //------------------------------------------------------------ // Deep background (Galaxy) //------------------------------------------------------------ if (styles.showGalaxyBackground && styles.deepBackgroundOpacity > 0f && galacticBounds.IntersectsWith(tileRect)) { using (RenderUtil.SaveState(graphics)) { graphics.MultiplyTransform(xformLinehanToMikesh); ImageHolder galaxyImage = styles.lightBackground ? s_galaxyImageGray : s_galaxyImage; RenderUtil.DrawImageAlpha(graphics, styles.deepBackgroundOpacity, galaxyImage, galaxyImageRect); } } timers.Add(new Timer("background (galaxy)")); #endregion #region pseudorandom-stars //------------------------------------------------------------ // Pseudo-Random Stars //------------------------------------------------------------ if (styles.pseudoRandomStars.visible) DrawPseudoRandomStars(); timers.Add(new Timer("pseudorandom")); #endregion #region rifts //------------------------------------------------------------ // Rifts in Charted Space //------------------------------------------------------------ if (styles.showRiftOverlay && styles.riftOpacity > 0f) RenderUtil.DrawImageAlpha(graphics, styles.riftOpacity, s_riftImage, riftImageRect); timers.Add(new Timer("rifts")); #endregion #region april-fools //------------------------------------------------------------ // April Fool's Day //------------------------------------------------------------ if (Silly) { using (RenderUtil.SaveState(graphics)) { // Render in image-space graphics.MultiplyTransform(worldSpaceToImageSpace); XImage sillyImage = styles.grayscale ? s_sillyImageGray : s_sillyImageColor; lock (sillyImage) { graphics.DrawImage(sillyImage, 0, 0, tileSize.Width, tileSize.Height); } } timers.Add(new Timer("silly")); } #endregion //------------------------------------------------------------ // Foreground //------------------------------------------------------------ #region macro-borders //------------------------------------------------------------ // Macro: Borders object //------------------------------------------------------------ if (styles.macroBorders.visible) { styles.macroBorders.pen.Apply(ref pen); graphics.SmoothingMode = XSmoothingMode.AntiAlias; foreach (var vec in borderFiles .Select(file => resourceManager.GetXmlFileObject(file, typeof(VectorObject))) .OfType<VectorObject>() .Where(vec => (vec.MapOptions & options & MapOptions.BordersMask) != 0)) { vec.Draw(graphics, tileRect, pen); } } timers.Add(new Timer("macro-borders")); #endregion #region macro-routes //------------------------------------------------------------ // Macro: Route object //------------------------------------------------------------ if (styles.macroRoutes.visible) { styles.macroRoutes.pen.Apply(ref pen); graphics.SmoothingMode = XSmoothingMode.AntiAlias; foreach (var vec in routeFiles .Select(file => resourceManager.GetXmlFileObject(file, typeof(VectorObject))) .OfType<VectorObject>() .Where(vec => (vec.MapOptions & options & MapOptions.BordersMask) != 0)) { vec.Draw(graphics, tileRect, pen); } } timers.Add(new Timer("macro-routes")); #endregion #region sector-grid //------------------------------------------------------------ // Sector Grid //------------------------------------------------------------ graphics.SmoothingMode = XSmoothingMode.HighSpeed; if (styles.sectorGrid.visible) { const int gridSlop = 10; styles.sectorGrid.pen.Apply(ref pen); for (float h = ((float)(Math.Floor((tileRect.Left) / Astrometrics.SectorWidth) - 1) - Astrometrics.ReferenceSector.X) * Astrometrics.SectorWidth - Astrometrics.ReferenceHex.X; h <= tileRect.Right + Astrometrics.SectorWidth; h += Astrometrics.SectorWidth) graphics.DrawLine(pen, h, tileRect.Top - gridSlop, h, tileRect.Bottom + gridSlop); for (float v = ((float)(Math.Floor((tileRect.Top) / Astrometrics.SectorHeight) - 1) - Astrometrics.ReferenceSector.Y) * Astrometrics.SectorHeight - Astrometrics.ReferenceHex.Y; v <= tileRect.Bottom + Astrometrics.SectorHeight; v += Astrometrics.SectorHeight) graphics.DrawLine(pen, tileRect.Left - gridSlop, v, tileRect.Right + gridSlop, v); } timers.Add(new Timer("sector grid")); #endregion #region subsector-grid //------------------------------------------------------------ // Subsector Grid //------------------------------------------------------------ graphics.SmoothingMode = XSmoothingMode.HighSpeed; if (styles.subsectorGrid.visible) { const int gridSlop = 10; styles.subsectorGrid.pen.Apply(ref pen); int hmin = (int)Math.Floor(tileRect.Left / Astrometrics.SubsectorWidth) - 1 - Astrometrics.ReferenceSector.X, hmax = (int)Math.Ceiling((tileRect.Right + Astrometrics.SubsectorWidth + Astrometrics.ReferenceHex.X) / Astrometrics.SubsectorWidth); for (int hi = hmin; hi <= hmax; ++hi) { if (hi % 4 == 0) continue; float h = hi * Astrometrics.SubsectorWidth - Astrometrics.ReferenceHex.X; graphics.DrawLine(pen, h, tileRect.Top - gridSlop, h, tileRect.Bottom + gridSlop); } int vmin = (int)Math.Floor(tileRect.Top / Astrometrics.SubsectorHeight) - 1 - Astrometrics.ReferenceSector.Y, vmax = (int)Math.Ceiling((tileRect.Bottom + Astrometrics.SubsectorHeight + Astrometrics.ReferenceHex.Y) / Astrometrics.SubsectorHeight); for (int vi = vmin; vi <= vmax; ++vi) { if (vi % 4 == 0) continue; float v = vi * Astrometrics.SubsectorHeight - Astrometrics.ReferenceHex.Y; graphics.DrawLine(pen, tileRect.Left - gridSlop, v, tileRect.Right + gridSlop, v); } } timers.Add(new Timer("subsector grid")); #endregion #region parsec-grid //------------------------------------------------------------ // Parsec Grid //------------------------------------------------------------ // TODO: Optimize - timers indicate this is slow graphics.SmoothingMode = XSmoothingMode.HighQuality; if (styles.parsecGrid.visible) DrawParsecGrid(); timers.Add(new Timer("parsec grid")); #endregion #region subsector-names //------------------------------------------------------------ // Subsector Names //------------------------------------------------------------ if (styles.subsectorNames.visible) { solidBrush.Color = styles.subsectorNames.textColor; foreach (Sector sector in selector.Sectors) { for (int i = 0; i < 16; i++) { Subsector ss = sector.Subsector(i); if (ss == null || string.IsNullOrEmpty(ss.Name)) continue; Point center = sector.SubsectorCenter(i); RenderUtil.DrawLabel(graphics, ss.Name, center, styles.subsectorNames.Font, solidBrush, styles.subsectorNames.textStyle); } } } timers.Add(new Timer("subsector names")); #endregion #region micro-borders //------------------------------------------------------------ // Micro: Borders //------------------------------------------------------------ if (styles.microBorders.visible) { if (styles.fillMicroBorders) DrawMicroBorders(BorderLayer.Fill); DrawMicroBorders(BorderLayer.Stroke); } timers.Add(new Timer("micro-borders")); #endregion #region micro-routes //------------------------------------------------------------ // Micro: Routes //------------------------------------------------------------ if (styles.microRoutes.visible) DrawRoutes(); timers.Add(new Timer("micro-routes")); #endregion #region micro-border-labels //------------------------------------------------------------ // Micro: Border Labels & Explicit Labels //------------------------------------------------------------ if (styles.showMicroNames) DrawLabels(); timers.Add(new Timer("micro-border labels")); #endregion #region sector-names //------------------------------------------------------------ // Sector Names //------------------------------------------------------------ if (styles.showSomeSectorNames || styles.showAllSectorNames) { foreach (Sector sector in selector.Sectors .Where(sector => styles.showAllSectorNames || (styles.showSomeSectorNames && sector.Selected)) .Where(sector => sector.Names.Any() || sector.Label != null)) { solidBrush.Color = styles.sectorName.textColor; string name = sector.Label ?? sector.Names[0].Text; RenderUtil.DrawLabel(graphics, name, sector.Center, styles.sectorName.Font, solidBrush, styles.sectorName.textStyle); } } timers.Add(new Timer("sector names")); #endregion #region government-rift-names //------------------------------------------------------------ // Macro: Government / Rift / Route Names //------------------------------------------------------------ if (styles.macroNames.visible) DrawMacroNames(); timers.Add(new Timer("macro names")); #endregion #region capitals-homeworlds //------------------------------------------------------------ // Macro: Capitals & Home Worlds //------------------------------------------------------------ if (styles.capitals.visible && (options & MapOptions.WorldsMask) != 0) { WorldObjectCollection worlds = resourceManager.GetXmlFileObject(@"~/res/Worlds.xml", typeof(WorldObjectCollection)) as WorldObjectCollection; if (worlds != null && worlds.Worlds != null) { solidBrush.Color = styles.capitals.textColor; foreach (WorldObject world in worlds.Worlds.Where(world => (world.MapOptions & options) != 0)) { world.Paint(graphics, styles.capitals.fillColor, solidBrush, styles.macroNames.SmallFont); } } } timers.Add(new Timer("macro worlds")); #endregion #region mega-names //------------------------------------------------------------ // Mega: Galaxy-Scale Labels //------------------------------------------------------------ if (styles.megaNames.visible) { solidBrush.Color = styles.megaNames.textColor; foreach (var label in megaLabels) { using (RenderUtil.SaveState(graphics)) { XMatrix matrix = new XMatrix(); matrix.ScalePrepend(1.0f / Astrometrics.ParsecScaleX, 1.0f / Astrometrics.ParsecScaleY); matrix.TranslatePrepend(label.position.X, label.position.Y); graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend); XFont font = label.minor ? styles.megaNames.SmallFont : styles.megaNames.Font; XSize size = graphics.MeasureString(label.text, font); graphics.TranslateTransform(-size.Width / 2, -size.Height / 2); // Center the text RectangleF textBounds = new RectangleF(0, 0, (float)size.Width * 1.01f, (float)size.Height * 2); // *2 or it gets cut off at high sizes XTextFormatter formatter = new XTextFormatter(graphics); formatter.Alignment = XParagraphAlignment.Center; formatter.DrawString(label.text, font, solidBrush, textBounds); } } } timers.Add(new Timer("mega names")); #endregion } // End of clipping, so world names are not clipped in jumpmaps. #region worlds //------------------------------------------------------------ // Worlds //------------------------------------------------------------ if (styles.worlds.visible) { // TODO: selector may be expensive foreach (World world in selector.Worlds) { DrawWorld(fonts, world, WorldLayer.Background); } foreach (World world in selector.Worlds) { DrawWorld(fonts, world, WorldLayer.Foreground); } } timers.Add(new Timer("worlds")); #endregion //------------------------------------------------------------ // Overlays //------------------------------------------------------------ #region droyne //------------------------------------------------------------ // Droyne/Chirper Worlds //------------------------------------------------------------ if (styles.droyneWorlds.visible) { solidBrush.Color = styles.droyneWorlds.textColor; foreach (World world in selector.Worlds) { bool droyne = world.HasCodePrefix("Droy") != null; bool chirpers = world.HasCodePrefix("Chir") != null; if (droyne || chirpers) { string glyph = droyne ? "\u2605" : "\u2606"; PointF center = Astrometrics.HexToCenter(world.Coordinates); using (RenderUtil.SaveState(graphics)) { XMatrix matrix = new XMatrix(); matrix.TranslatePrepend(center.X, center.Y); matrix.ScalePrepend(1 / Astrometrics.ParsecScaleX, 1 / Astrometrics.ParsecScaleY); graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend); graphics.DrawString(glyph, styles.droyneWorlds.Font, solidBrush, 0, 0, RenderUtil.StringFormatCentered); } } } } timers.Add(new Timer("droyne")); #endregion #region unofficial //------------------------------------------------------------ // Unofficial //------------------------------------------------------------ if (styles.dimUnofficialSectors && styles.worlds.visible) { solidBrush.Color = Color.FromArgb(128, styles.backgroundColor); foreach (Sector sector in selector.Sectors .Where(sector => !sector.Tags.Contains("Official") && !sector.Tags.Contains("Preserve") && !sector.Tags.Contains("InReview"))) graphics.DrawRectangle(solidBrush, sector.Bounds); } timers.Add(new Timer("unofficial")); #endregion #region timing #if SHOW_TIMING using( RenderUtil.SaveState( graphics ) ) { XFont font = new XFont( FontFamily.GenericSansSerif, 12, XFontStyle.Regular, new XPdfFontOptions(PdfSharp.Pdf.PdfFontEncoding.Unicode) ); graphics.MultiplyTransform( worldSpaceToImageSpace ); double cursorX = 20.0, cursorY = 20.0; DateTime last = dtStart; foreach( Timer s in timers ) { TimeSpan ts = s.dt - last; last = s.dt; for( int dx = -1; dx <= 1; ++dx ) { for( int dy = -1; dy <= 1; ++dy ) { graphics.DrawString( String.Format( "{0} {1}", Math.Round( ts.TotalMilliseconds ), s.label ), font, XBrushes.Black, cursorX + dx, cursorY + dy ); } } graphics.DrawString( String.Format("{0} {1}", Math.Round(ts.TotalMilliseconds), s.label), font, XBrushes.Yellow, cursorX, cursorY ); cursorY += 14; } } #endif #endregion } }
/// <summary> /// Demonstrates the use of XGraphics.Transform. /// </summary> public override void RenderPage(XGraphics gfx) { XGraphicsState state1, state2; base.RenderPage(gfx); state1 = gfx.Save(); // Level 1 gfx.TranslateTransform(20, 50); gfx.DrawLine(XPens.Blue, 0, 0, 10, 10); gfx.Restore(state1); state1 = gfx.Save(); // Level 2 gfx.TranslateTransform(220, 50); gfx.DrawLine(XPens.Blue, 0, 0, 10, 10); XGraphicsPath clipPath = new XGraphicsPath(); clipPath.AddPie(0, 10, 150, 100, -50, 100); gfx.IntersectClip(clipPath); gfx.DrawRectangle(XBrushes.LightYellow, 0, 0, 1000, 1000); state2 = gfx.Save(); // Level 3 gfx.ScaleTransform(10); gfx.DrawLine(XPens.Red, 1, 1, 10, 10); //gfx.ResetClip(); gfx.Restore(state2); // Level 2 gfx.DrawLine(XPens.Red, 1, 1, 10, 10); gfx.Restore(state1); #if true_ gfx.SetClip(new XRect(20, 20, 300, 500)); gfx.DrawRectangle(XBrushes.Yellow, 0, 0, gfx.PageSize.Width, gfx.PageSize.Height); gfx.SetClip(new XRect(100, 200, 300, 500), XCombineMode.Intersect); gfx.DrawRectangle(XBrushes.LightBlue, 0, 0, gfx.PageSize.Width, gfx.PageSize.Height); gfx.DrawLine(XPens.MediumSlateBlue, 0, 0, 150, 200); gfx.DrawPolygon(properties.Pen1.Pen, GetPentagram(75, new PointF(150, 200))); Matrix matrix = new Matrix(); //matrix.Scale(2f, 1.5f); //matrix.Translate(-200, -400); //matrix.Rotate(45); //matrix.Translate(200, 400); //gfx.Transform = matrix; //gfx.TranslateTransform(50, 30); #if true gfx.TranslateTransform(30, 40, XMatrixOrder.Prepend); gfx.ScaleTransform(2.0f, 2.0f, XMatrixOrder.Prepend); gfx.RotateTransform(15, XMatrixOrder.Prepend); #else gfx.TranslateTransform(30, 40, XMatrixOrder.Append); gfx.ScaleTransform(2.0f, 2.0f, XMatrixOrder.Append); gfx.RotateTransform(15, XMatrixOrder.Append); #endif bool id = matrix.IsIdentity; matrix.Scale(2.0f, 2.0f, MatrixOrder.Prepend); //matrix.Translate(30, -50); matrix.Rotate(15, MatrixOrder.Prepend); Matrix mtx = gfx.Transform.ToMatrix(); //gfx.Transform = matrix; gfx.DrawLine(XPens.MediumSlateBlue, 0, 0, 150, 200); gfx.DrawPolygon(properties.Pen2.Pen, GetPentagram(75, new PointF(150, 200))); gfx.ResetClip(); gfx.DrawLine(XPens.Red, 0, 0, 1000, 1000); gfx.DrawPolygon(XPens.SandyBrown, GetPentagram(75, new PointF(150, 200))); #endif }
public override void Draw(XGraphics graphics, Palette palette, DrawingContext context) { Random random = new Random(Name.GetHashCode()); var topLeft = InnerBounds.GetCorner(CompassPoint.NorthWest); var topRight = InnerBounds.GetCorner(CompassPoint.NorthEast); var bottomLeft = InnerBounds.GetCorner(CompassPoint.SouthWest); var bottomRight = InnerBounds.GetCorner(CompassPoint.SouthEast); var topCenter = InnerBounds.GetCorner(CompassPoint.North); var rightCenter = InnerBounds.GetCorner(CompassPoint.East); var bottomCenter = InnerBounds.GetCorner(CompassPoint.South); var leftCenter = InnerBounds.GetCorner(CompassPoint.West); var top = new LineSegment(topLeft, topRight); var right = new LineSegment(topRight, bottomRight); var bottom = new LineSegment(bottomRight, bottomLeft); var left = new LineSegment(bottomLeft, topLeft); var halfTopRight = new LineSegment(topCenter, topRight); var halfBottomRight = new LineSegment(bottomRight, bottomCenter); var centerVertical = new LineSegment(bottomCenter, topCenter); var centerHorizontal = new LineSegment(leftCenter, rightCenter); var halfRightBottom = new LineSegment(rightCenter, bottomRight); var halfLeftBottom = new LineSegment(bottomLeft, leftCenter); var slantUp = new LineSegment(bottomLeft, topRight); var slantDown = new LineSegment(bottomRight, topLeft); context.LinesDrawn.Add(top); context.LinesDrawn.Add(right); context.LinesDrawn.Add(bottom); context.LinesDrawn.Add(left); var brush = context.Selected ? palette.BorderBrush : palette.FillBrush; // Room specific fill brush (White shows global color) if (RoomFill != ColorTranslator.FromHtml("White") && RoomFill != ColorTranslator.FromHtml("#FFFFFF")) { brush = new SolidBrush(RoomFill); } if (!Settings.DebugDisableLineRendering) { var path = palette.Path(); Drawing.AddLine(path, top, random); Drawing.AddLine(path, right, random); Drawing.AddLine(path, bottom, random); Drawing.AddLine(path, left, random); graphics.DrawPath(brush, path); // Second fill for room specific colors with a split option if (SecondFill != ColorTranslator.FromHtml("White") && SecondFill != ColorTranslator.FromHtml("#FFFFFF")) { // Set the second fill color brush = new SolidBrush(SecondFill); // Define the second path based on the second fill location var secondPath = palette.Path(); switch (SecondFillLocation) { case "Bottom": Drawing.AddLine(secondPath, centerHorizontal, random); Drawing.AddLine(secondPath, halfRightBottom, random); Drawing.AddLine(secondPath, bottom, random); Drawing.AddLine(secondPath, halfLeftBottom, random); break; case "BottomRight": Drawing.AddLine(secondPath, slantUp, random); Drawing.AddLine(secondPath, right, random); Drawing.AddLine(secondPath, bottom, random); break; case "Right": Drawing.AddLine(secondPath, halfTopRight, random); Drawing.AddLine(secondPath, right, random); Drawing.AddLine(secondPath, halfBottomRight, random); Drawing.AddLine(secondPath, centerVertical, random); break; case "TopRight": Drawing.AddLine(secondPath, top, random); Drawing.AddLine(secondPath, right, random); Drawing.AddLine(secondPath, slantDown, random); break; default: break; } // Draw the second fill over the first graphics.DrawPath(brush, secondPath); } if (IsDark) { var state = graphics.Save(); graphics.IntersectClip(path); brush = context.Selected ? palette.FillBrush : palette.BorderBrush; // Room specific fill brush (White shows global color) if (RoomBorder != ColorTranslator.FromHtml("White") && RoomBorder != ColorTranslator.FromHtml("#FFFFFF")) { brush = new SolidBrush(RoomBorder); } graphics.DrawPolygon(brush, new PointF[] { topRight.ToPointF(), new PointF(topRight.X - Settings.DarknessStripeSize, topRight.Y), new PointF(topRight.X, topRight.Y + Settings.DarknessStripeSize) }, XFillMode.Alternate); graphics.Restore(state); } if (RoomBorder == ColorTranslator.FromHtml("White") || RoomBorder == ColorTranslator.FromHtml("#FFFFFF")) { graphics.DrawPath(palette.BorderPen, path); } else { var RoomBorderPen = new Pen(RoomBorder, Settings.LineWidth); RoomBorderPen.StartCap = LineCap.Round; RoomBorderPen.EndCap = LineCap.Round; graphics.DrawPath(RoomBorderPen, path); } } var font = Settings.LargeFont; brush = context.Selected ? palette.FillBrush : palette.LargeTextBrush; // Room specific fill brush (White shows global color) if (RoomLargeText != ColorTranslator.FromHtml("White") && RoomLargeText != ColorTranslator.FromHtml("#FFFFFF")) { brush = new SolidBrush(RoomLargeText); } Rect textBounds = InnerBounds; textBounds.Inflate(-5, -5); if (textBounds.Width > 0 && textBounds.Height > 0) { m_name.Draw(graphics, font, brush, textBounds.Position, textBounds.Size, XStringFormats.Center); } var expandedBounds = InnerBounds; expandedBounds.Inflate(Settings.ObjectListOffsetFromRoom, Settings.ObjectListOffsetFromRoom); var drawnObjectList = false; font = Settings.SmallFont; brush = palette.SmallTextBrush; // Room specific fill brush (White shows global color) if (RoomSmallText != ColorTranslator.FromHtml("White") && RoomSmallText != ColorTranslator.FromHtml("#FFFFFF")) { brush = new SolidBrush(RoomSmallText); } if (!string.IsNullOrEmpty(Objects)) { XStringFormat format = new XStringFormat(); Vector pos = expandedBounds.GetCorner(m_objectsPosition); if (!Drawing.SetAlignmentFromCardinalOrOrdinalDirection(format, m_objectsPosition)) { // object list appears inside the room below its name format.LineAlignment = XLineAlignment.Far; format.Alignment = XStringAlignment.Near; //format.Trimming = StringTrimming.EllipsisCharacter; //format.FormatFlags = StringFormatFlags.LineLimit; var height = InnerBounds.Height / 2 - font.Height / 2; var bounds = new Rect(InnerBounds.Left + Settings.ObjectListOffsetFromRoom, InnerBounds.Bottom - height, InnerBounds.Width - Settings.ObjectListOffsetFromRoom, height - Settings.ObjectListOffsetFromRoom); brush = context.Selected ? palette.FillBrush : brush; if (bounds.Width > 0 && bounds.Height > 0) { m_objects.Draw(graphics, font, brush, bounds.Position, bounds.Size, format); } drawnObjectList = true; } else if (m_objectsPosition == CompassPoint.North || m_objectsPosition == CompassPoint.South) { pos.X += Settings.ObjectListOffsetFromRoom; } if (!drawnObjectList) { m_objects.Draw(graphics, font, brush, pos, Vector.Zero, format); } } }