Пример #1
0
    /// <summary>
    /// Creates an XForm from an image brush.
    /// </summary>
    public static XForm FromImageBrush(DocumentRenderingContext context, ImageBrush brush)
    {
      XPImage xpImage = ImageBuilder.FromImageBrush(context, brush);
      XImage ximage = xpImage.XImage;
      double width = ximage.PixelWidth;
      double height = ximage.PixelHeight;

      // view box in point
      // XRect box = new XRect(brush.Viewbox.X * 0.75, brush.Viewbox.Y * 0.75, brush.Viewbox.Width * 0.75, brush.Viewbox.Height * 0.75);
      XRect box = new XRect(0, 0, width, height);
      XForm xform = new XForm(context.PdfDocument, box);

      PdfContentWriter formWriter = new PdfContentWriter(context, xform, RenderMode.Default);

      Debug.Assert(ximage != null);

      PdfFormXObject pdfForm = xform.PdfForm;
      pdfForm.Elements.SetMatrix(PdfFormXObject.Keys.Matrix, new XMatrix());

      //formWriter.Size = brush.Viewport.Size;
      formWriter.BeginContentRaw();

      string imageID = formWriter.Resources.AddImage(new PdfImage(context.PdfDocument, ximage));
      XMatrix matrix = new XMatrix();
      double scaleX = brush.Viewport.Width / brush.Viewbox.Width * 4 / 3 * ximage.PointWidth;
      double scaleY = brush.Viewport.Height / brush.Viewbox.Height * 4 / 3 * ximage.PointHeight;
      matrix.TranslatePrepend(-brush.Viewbox.X, -brush.Viewbox.Y);
      matrix.ScalePrepend(scaleX, scaleY);
      matrix.TranslatePrepend(brush.Viewport.X / scaleX, brush.Viewport.Y / scaleY);

      matrix = new XMatrix(width, 0, 0, -height, 0, height);
      formWriter.WriteLiteral("q\n");
      // TODO:WriteClip(path.Data);
      //formWriter.WriteLiteral("{0:0.###} 0 0 -{1:0.###} {2:0.###} {3:0.###} cm 100 Tz {4} Do Q\n",
      //  matrix.M11, matrix.M22, matrix.OffsetX, matrix.OffsetY + brush.Viewport.Height, imageID);
      formWriter.WriteMatrix(matrix);
      formWriter.WriteLiteral(imageID + " Do Q\n");

      formWriter.EndContent();

      return xform;
    }
Пример #2
0
        private static void DrawWorld(RenderContext ctx, FontCache styleRes, World world, WorldLayer layer)
        {
            bool isPlaceholder = world.IsPlaceholder;
            bool isCapital = world.IsCapital;
            bool isHiPop = world.IsHi;
            bool renderName = ctx.styles.worldDetails.HasFlag(WorldDetails.AllNames) ||
                (ctx.styles.worldDetails.HasFlag(WorldDetails.KeyNames) && (isCapital || isHiPop));
            bool renderUWP = ctx.styles.worldDetails.HasFlag(WorldDetails.Uwp);

            using (RenderUtil.SaveState(ctx.graphics))
            {
                XPen pen = new XPen(XColor.Empty);
                XSolidBrush solidBrush = new XSolidBrush();

                ctx.graphics.SmoothingMode = XSmoothingMode.AntiAlias;

                // Center on the parsec
                PointF center = Astrometrics.HexToCenter(world.Coordinates);

                XMatrix matrix = new XMatrix();
                matrix.TranslatePrepend(center.X, center.Y);
                matrix.ScalePrepend(ctx.styles.hexContentScale / Astrometrics.ParsecScaleX, ctx.styles.hexContentScale / Astrometrics.ParsecScaleY);
                ctx.graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend);

                if (!ctx.styles.useWorldImages)
                {
                    if (layer == WorldLayer.Background)
                    {
                        #region Zone
                        if (ctx.styles.worldDetails.HasFlag(WorldDetails.Zone))
                        {
                            Stylesheet.StyleElement? maybeElem = ZoneStyle(ctx, world);
                            if (maybeElem.HasValue)
                            {
                                Stylesheet.StyleElement elem = maybeElem.Value;
                                if (!elem.fillColor.IsEmpty)
                                {
                                    solidBrush.Color = elem.fillColor;
                                    ctx.graphics.DrawEllipse(solidBrush, -0.4f, -0.4f, 0.8f, 0.8f);
                                }

                                PenInfo pi = elem.pen;
                                if (!pi.color.IsEmpty)
                                {
                                    pi.Apply(ref pen);

                                    if (renderName && ctx.styles.fillMicroBorders)
                                    {
                                        using (RenderUtil.SaveState(ctx.graphics))
                                        {
                                            ctx.graphics.IntersectClip(new RectangleF(-.5f, -.5f, 1f, renderUWP ? 0.65f : 0.75f));
                                            ctx.graphics.DrawEllipse(pen, -0.4f, -0.4f, 0.8f, 0.8f);
                                        }
                                    }
                                    else
                                    {
                                        ctx.graphics.DrawEllipse(pen, -0.4f, -0.4f, 0.8f, 0.8f);
                                    }
                                }
                            }
                        }
                        #endregion

                        #region Hex
                        if (!ctx.styles.numberAllHexes &&
                            ctx.styles.worldDetails.HasFlag(WorldDetails.Hex))
                        {
                            string hex;
                            switch (ctx.styles.hexCoordinateStyle)
                            {
                                default:
                                case Stylesheet.HexCoordinateStyle.Sector: hex = world.Hex; break;
                                case Stylesheet.HexCoordinateStyle.Subsector: hex = world.SubsectorHex; break;
                            }
                            solidBrush.Color = ctx.styles.hexNumber.textColor;
                            ctx.graphics.DrawString(hex, ctx.styles.hexNumber.Font, solidBrush, 0.0f, -0.5f, RenderUtil.StringFormatTopCenter);
                        }
                        #endregion
                    }

                    if (layer == WorldLayer.Foreground)
                    {
                        Stylesheet.StyleElement? elem = ZoneStyle(ctx, world);
                        TextBackgroundStyle worldTextBackgroundStyle = (elem.HasValue && !elem.Value.fillColor.IsEmpty)
                            ? TextBackgroundStyle.None : ctx.styles.worlds.textBackgroundStyle;

                        #region Name
                        if (renderName)
                        {
                            string name = world.Name;
                            if ((isHiPop && ctx.styles.worldDetails.HasFlag(WorldDetails.Highlight)) || ctx.styles.worlds.textStyle.Uppercase)
                                name = name.ToUpperInvariant();

                            Color textColor = (isCapital && ctx.styles.worldDetails.HasFlag(WorldDetails.Highlight))
                                ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor;
                            XFont font = ((isHiPop || isCapital) && ctx.styles.worldDetails.HasFlag(WorldDetails.Highlight))
                                ? ctx.styles.worlds.LargeFont : ctx.styles.worlds.Font;

                            DrawWorldLabel(ctx, worldTextBackgroundStyle, solidBrush, textColor, ctx.styles.worlds.textStyle.Translation, font, name);
                        }
                        #endregion

                        #region Allegiance
                        // TODO: Mask off background for allegiance
                        if (ctx.styles.worldDetails.HasFlag(WorldDetails.Allegiance))
                        {
                            string alleg = world.Allegiance;
                            if (!SecondSurvey.IsDefaultAllegiance(alleg))
                            {
                                if (!ctx.styles.t5AllegianceCodes && alleg.Length > 2)
                                    alleg = SecondSurvey.T5AllegianceCodeToLegacyCode(alleg);

                                solidBrush.Color = ctx.styles.worlds.textColor;

                                if (ctx.styles.lowerCaseAllegiance)
                                    alleg = alleg.ToLowerInvariant();

                                ctx.graphics.DrawString(alleg, ctx.styles.worlds.SmallFont, solidBrush, ctx.styles.AllegiancePosition.X, ctx.styles.AllegiancePosition.Y, RenderUtil.StringFormatCentered);
                            }
                        }
                        #endregion

                        if (!isPlaceholder)
                        {
                            #region GasGiant
                            if (ctx.styles.worldDetails.HasFlag(WorldDetails.GasGiant))
                            {
                                if (world.GasGiants > 0)
                                {
                                    solidBrush.Color = ctx.styles.worlds.textColor;
                                    RenderUtil.DrawGlyph(ctx.graphics, Glyph.Circle, styleRes, solidBrush, ctx.styles.GasGiantPosition.X, ctx.styles.GasGiantPosition.Y);
                                }
                            }
                            #endregion

                            #region Starport
                            if (ctx.styles.worldDetails.HasFlag(WorldDetails.Starport))
                            {
                                string starport = world.Starport.ToString();
                                DrawWorldLabel(ctx, worldTextBackgroundStyle, solidBrush, ctx.styles.worlds.textColor, ctx.styles.StarportPosition, styleRes.StarportFont, starport);
                            }
                            #endregion

                            #region UWP
                            if (renderUWP)
                            {
                                string uwp = world.UWP;
                                solidBrush.Color = ctx.styles.worlds.textColor;

                                ctx.graphics.DrawString(uwp, ctx.styles.hexNumber.Font, solidBrush, ctx.styles.StarportPosition.X, -ctx.styles.StarportPosition.Y, RenderUtil.StringFormatCentered);
                            }
                            #endregion

                            #region Bases
                            // TODO: Mask off background for glyphs
                            if (ctx.styles.worldDetails.HasFlag(WorldDetails.Bases))
                            {
                                string bases = world.Bases;

                                // Special case: Show Zho Naval+Military as diamond
                                if (world.BaseAllegiance == "Zh" && bases == "KM")
                                    bases = "Z";

                                // Base 1
                                bool bottomUsed = false;
                                if (bases.Length > 0)
                                {
                                    Glyph glyph = Glyph.FromBaseCode(world.BaseAllegiance, bases[0]);
                                    if (glyph.Printable)
                                    {
                                        PointF pt = ctx.styles.BaseTopPosition;
                                        if (glyph.Bias == Glyph.GlyphBias.Bottom)
                                        {
                                            pt = ctx.styles.BaseBottomPosition;
                                            bottomUsed = true;
                                        }

                                        solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor;
                                        RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, pt.X, pt.Y);
                                    }
                                }

                                // Base 2
                                if (bases.Length > 1)
                                {
                                    Glyph glyph = Glyph.FromBaseCode(world.LegacyAllegiance, bases[1]);
                                    if (glyph.Printable)
                                    {
                                        PointF pt = bottomUsed ? ctx.styles.BaseTopPosition : ctx.styles.BaseBottomPosition;
                                        solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor;
                                        RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, pt.X, pt.Y);
                                    }
                                }

                                // Research Stations
                                string rs;
                                if ((rs = world.ResearchStation) != null)
                                {
                                    Glyph glyph = Glyph.FromResearchCode(rs);
                                    solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor;
                                    RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, ctx.styles.BaseMiddlePosition.X, ctx.styles.BaseMiddlePosition.Y);
                                }
                                else if (world.IsReserve)
                                {
                                    Glyph glyph = Glyph.Reserve;
                                    solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor;
                                    RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, ctx.styles.BaseMiddlePosition.X, 0);
                                }
                                else if (world.IsPenalColony)
                                {
                                    Glyph glyph = Glyph.Prison;
                                    solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor;
                                    RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, ctx.styles.BaseMiddlePosition.X, 0);
                                }
                                else if (world.IsPrisonExileCamp)
                                {
                                    Glyph glyph = Glyph.ExileCamp;
                                    solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor;
                                    RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, ctx.styles.BaseMiddlePosition.X, 0);
                                }
                            }
                            #endregion
                        }

                        #region Disc
                        if (ctx.styles.worldDetails.HasFlag(WorldDetails.Type))
                        {
                            if (isPlaceholder)
                            {
                                DrawWorldLabel(ctx, ctx.styles.placeholder.textBackgroundStyle, solidBrush, ctx.styles.placeholder.textColor, ctx.styles.placeholder.position, ctx.styles.placeholder.Font, ctx.styles.placeholder.content);
                            }
                            else
                            {
                                if (world.Size <= 0)
                                {
                                    #region Asteroid-Belt
                                    if (ctx.styles.worldDetails.HasFlag(WorldDetails.Asteroids))
                                    {
                                        // Basic pattern, with probability varying per position:
                                        //   o o o
                                        //  o o o o
                                        //   o o o

                                        int[] lpx = { -2, 0, 2, -3, -1, 1, 3, -2, 0, 2 };
                                        int[] lpy = { -2, -2, -2, 0, 0, 0, 0, 2, 2, 2 };
                                        float[] lpr = { 0.5f, 0.9f, 0.5f, 0.6f, 0.9f, 0.9f, 0.6f, 0.5f, 0.9f, 0.5f };

                                        solidBrush.Color = ctx.styles.worlds.textColor;

                                        // Random generator is seeded with world location so it is always the same
                                        Random rand = new Random(world.Coordinates.X ^ world.Coordinates.Y);
                                        for (int i = 0; i < lpx.Length; ++i)
                                        {
                                            if (rand.NextDouble() < lpr[i])
                                            {
                                                float px = lpx[i] * 0.035f;
                                                float py = lpy[i] * 0.035f;

                                                float w = 0.04f + (float)rand.NextDouble() * 0.03f;
                                                float h = 0.04f + (float)rand.NextDouble() * 0.03f;

                                                // If necessary, add jitter here
                                                float dx = 0, dy = 0;

                                                ctx.graphics.DrawEllipse(solidBrush,
                                                    px + dx - w / 2, py + dy - h / 2, w, h);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        // Just a glyph
                                        solidBrush.Color = ctx.styles.worlds.textColor;
                                        RenderUtil.DrawGlyph(ctx.graphics, Glyph.DiamondX, styleRes, solidBrush, 0.0f, 0.0f);
                                    }
                                    #endregion
                                }
                                else
                                {
                                    XColor penColor, brushColor;
                                    ctx.styles.WorldColors(world, out penColor, out brushColor);

                                    if (!brushColor.IsEmpty)
                                    {
                                        solidBrush.Color = brushColor;
                                        ctx.graphics.DrawEllipse(solidBrush, -0.1f, -0.1f, 0.2f, 0.2f);
                                    }

                                    if (!penColor.IsEmpty)
                                    {
                                        ctx.styles.worldWater.pen.Apply(ref pen);
                                        pen.Color = penColor;
                                        ctx.graphics.DrawEllipse(pen, -0.1f, -0.1f, 0.2f, 0.2f);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // Dotmap
                            solidBrush.Color = ctx.styles.worlds.textColor;
                            ctx.graphics.DrawEllipse(solidBrush, -0.2f, -0.2f, 0.4f, 0.4f);
                        }
                        #endregion
                    }
                }
                else // ctx.styles.useWorldImages
                {
                    float imageRadius = ((world.Size <= 0) ? 0.6f : (0.3f * (world.Size / 5.0f + 0.2f))) / 2;
                    float decorationRadius = imageRadius;

                    if (layer == WorldLayer.Background)
                    {
                        #region Disc
                        if (ctx.styles.worldDetails.HasFlag(WorldDetails.Type))
                        {
                            if (isPlaceholder)
                            {
                                DrawWorldLabel(ctx, ctx.styles.placeholder.textBackgroundStyle, solidBrush, ctx.styles.placeholder.textColor, ctx.styles.placeholder.position, ctx.styles.placeholder.Font, ctx.styles.placeholder.content);
                            }
                            else if (world.Size <= 0)
                            {
                                const float scaleX = 1.5f;
                                const float scaleY = 1.0f;
                                XImage img = s_worldImages["Belt"];

                                lock (img)
                                {
                                    ctx.graphics.DrawImage(img, -imageRadius * scaleX, -imageRadius * scaleY, imageRadius * 2 * scaleX, imageRadius * 2 * scaleY);
                                }
                            }
                            else
                            {
                                XImage img;
                                switch (world.Hydrographics)
                                {
                                    default:
                                    case 0x0: img = s_worldImages["Hyd0"]; break;
                                    case 0x1: img = s_worldImages["Hyd1"]; break;
                                    case 0x2: img = s_worldImages["Hyd2"]; break;
                                    case 0x3: img = s_worldImages["Hyd3"]; break;
                                    case 0x4: img = s_worldImages["Hyd4"]; break;
                                    case 0x5: img = s_worldImages["Hyd5"]; break;
                                    case 0x6: img = s_worldImages["Hyd6"]; break;
                                    case 0x7: img = s_worldImages["Hyd7"]; break;
                                    case 0x8: img = s_worldImages["Hyd8"]; break;
                                    case 0x9: img = s_worldImages["Hyd9"]; break;
                                    case 0xA: img = s_worldImages["HydA"]; break;
                                }
                                if (img != null)
                                {
                                    lock (img)
                                    {
                                        ctx.graphics.DrawImage(img, -imageRadius, -imageRadius, imageRadius * 2, imageRadius * 2);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // Dotmap
                            solidBrush.Color = ctx.styles.worlds.textColor;
                            ctx.graphics.DrawEllipse(solidBrush, -0.2f, -0.2f, 0.4f, 0.4f);
                        }
                        #endregion
                    }

                    if (isPlaceholder)
                        return;

                    if (layer == WorldLayer.Foreground)
                    {
                        #region Zone
                        if (ctx.styles.worldDetails.HasFlag(WorldDetails.Zone))
                        {
                            if (world.IsAmber || world.IsRed || world.IsBlue)
                            {
                                PenInfo pi =
                                    world.IsAmber ? ctx.styles.amberZone.pen :
                                    world.IsRed ? ctx.styles.redZone.pen : ctx.styles.blueZone.pen;
                                pi.Apply(ref pen);

                                // TODO: Try and accomplish this using dash pattern
                                decorationRadius += 0.1f;
                                ctx.graphics.DrawArc(pen, -decorationRadius, -decorationRadius, decorationRadius * 2, decorationRadius * 2, 5, 80);
                                ctx.graphics.DrawArc(pen, -decorationRadius, -decorationRadius, decorationRadius * 2, decorationRadius * 2, 95, 80);
                                ctx.graphics.DrawArc(pen, -decorationRadius, -decorationRadius, decorationRadius * 2, decorationRadius * 2, 185, 80);
                                ctx.graphics.DrawArc(pen, -decorationRadius, -decorationRadius, decorationRadius * 2, decorationRadius * 2, 275, 80);
                            }
                        }
                        #endregion

                        #region GasGiant
                        if (ctx.styles.worldDetails.HasFlag(WorldDetails.GasGiant))
                        {
                            if (world.GasGiants > 0)
                            {
                                decorationRadius += 0.1f;
                                const float symbolRadius = 0.05f;
                                solidBrush.Color = ctx.styles.worlds.textHighlightColor; ;
                                ctx.graphics.DrawEllipse(solidBrush, decorationRadius - symbolRadius, 0.0f - symbolRadius, symbolRadius * 2, symbolRadius * 2);
                            }
                        }
                        #endregion

                        #region UWP
                        if (renderUWP)
                        {
                            string uwp = world.UWP;
                            solidBrush.Color = ctx.styles.worlds.textColor;

                            using (RenderUtil.SaveState(ctx.graphics))
                            {
                                XMatrix uwpMatrix = new XMatrix();
                                uwpMatrix.TranslatePrepend(decorationRadius, 0.0f);
                                uwpMatrix.ScalePrepend(ctx.styles.worlds.textStyle.Scale.Width, ctx.styles.worlds.textStyle.Scale.Height);
                                uwpMatrix.Multiply(uwpMatrix, XMatrixOrder.Prepend);
                                ctx.graphics.DrawString(uwp, ctx.styles.hexNumber.Font, solidBrush, ctx.styles.StarportPosition.X, -ctx.styles.StarportPosition.Y, RenderUtil.StringFormatCenterLeft);
                            }
                        }
                        #endregion

                        #region Name
                        if (renderName)
                        {
                            string name = world.Name;
                            if (isHiPop)
                                name = name.ToUpperInvariant();

                            using (RenderUtil.SaveState(ctx.graphics))
                            {
                                Color textColor = (isCapital && ctx.styles.worldDetails.HasFlag(WorldDetails.Highlight))
                                    ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor;

                                if (ctx.styles.worlds.textStyle.Uppercase)
                                    name = name.ToUpper();

                                decorationRadius += 0.1f;
                                XMatrix imageMatrix = new XMatrix();
                                imageMatrix.TranslatePrepend(decorationRadius, 0.0f);
                                imageMatrix.ScalePrepend(ctx.styles.worlds.textStyle.Scale.Width, ctx.styles.worlds.textStyle.Scale.Height);
                                imageMatrix.TranslatePrepend(ctx.graphics.MeasureString(name, ctx.styles.worlds.Font).Width / 2, 0.0f); // Left align
                                ctx.graphics.MultiplyTransform(imageMatrix, XMatrixOrder.Prepend);

                                DrawWorldLabel(ctx, ctx.styles.worlds.textBackgroundStyle, solidBrush, textColor, ctx.styles.worlds.textStyle.Translation, ctx.styles.worlds.Font, name);
                            }
                        }
                        #endregion
                    }
                }
            }
        }
Пример #3
0
        public static void RenderTile(RenderContext ctx)
        {
            DateTime dtStart = DateTime.Now;
            List<Timer> timers = new List<Timer>();

            if (ctx.resourceManager == null)
                throw new ArgumentNullException("resourceManager");

            if (ctx.graphics == null)
                throw new ArgumentNullException("graphics");

            if (ctx.selector == null)
                throw new ArgumentNullException("selector");

            XSolidBrush solidBrush = new XSolidBrush();
            XPen pen = new XPen(XColor.Empty);

            using (var fonts = new FontCache(ctx.styles))
            {
                #region resources
                lock (s_imageInitLock)
                {
                    if (ctx.styles.useBackgroundImage && s_backgroundImage == null)
                        s_backgroundImage = XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Nebula.png"));

                    if (ctx.styles.showRifts && s_riftImage == null)
                        s_riftImage = new ImageHolder(Image.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Rifts.png")));

                    if (ctx.styles.useGalaxyImage && s_galaxyImage == null) {
                        s_galaxyImage = new ImageHolder(Image.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Galaxy.png")));
                        s_galaxyImageGray = new ImageHolder(Image.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Galaxy_Gray.png")));
                    }

                    if (ctx.styles.useWorldImages && s_worldImages == null)
                    {
                        s_worldImages = new Dictionary<string, XImage> {
                            { "Hyd0", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Hyd0.png")) },
                            { "Hyd1", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Hyd1.png")) },
                            { "Hyd2", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Hyd2.png")) },
                            { "Hyd3", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Hyd3.png")) },
                            { "Hyd4", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Hyd4.png")) },
                            { "Hyd5", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Hyd5.png")) },
                            { "Hyd6", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Hyd6.png")) },
                            { "Hyd7", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Hyd7.png")) },
                            { "Hyd8", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Hyd8.png")) },
                            { "Hyd9", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Hyd9.png")) },
                            { "HydA", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/HydA.png")) },
                            { "Belt", XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/Candy/Belt.png")) }
                        };
                    }

                    if (ctx.silly && s_sillyImageColor == null)
                    {
                        // Happy face c/o http://bighappyfaces.com/
                        s_sillyImageColor = XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/AprilFools/Starburst.png"));
                        s_sillyImageGray = XImage.FromFile(ctx.resourceManager.Server.MapPath(@"~/res/AprilFools/Starburst_Gray.png"));
                    }
                }
                #endregion

                timers.Add(new Timer("preload"));
                //////////////////////////////////////////////////////////////
                //
                // Image-Space Rendering
                //
                //////////////////////////////////////////////////////////////

                using (Maps.Rendering.RenderUtil.SaveState(ctx.graphics))
                {
                    if (ctx.clipPath != null)
                    {
                        XMatrix m = ctx.ImageSpaceToWorldSpace;
                        ctx.graphics.MultiplyTransform(m);
                        ctx.graphics.IntersectClip(ctx.clipPath);
                        m.Invert();
                        ctx.graphics.MultiplyTransform(m);
                    }

                    // Fill
                    ctx.graphics.SmoothingMode = XSmoothingMode.HighSpeed;
                    solidBrush.Color = ctx.styles.backgroundColor;
                    ctx.graphics.DrawRectangle(solidBrush, 0, 0, ctx.tileSize.Width, ctx.tileSize.Height);

                    //// Draw tile #
                    //using( var font = new Font( FontFamily.GenericSansSerif, 10 ) )
                    //{
                    //  graphics.DrawString( String.Format( "({0},{1})", x, y ), font, foregroundBrush, 0, 0 );
                    //  graphics.DrawString( String.Format( "{0},{1}-{2}x{3}", tileRect.X, tileRect.Y, tileRect.Width, tileRect.Height ), font, foregroundBrush, 0, 20 );
                    //}

                    // Frame it
                    //graphics.DrawRectangle( Pens.Green, 0, 0, tileSize.Width-1, tileSize.Height-1 );
                }

                timers.Add(new Timer("imagespace"));
                //////////////////////////////////////////////////////////////
                //
                // World-Space Rendering
                //
                //////////////////////////////////////////////////////////////

                // Transform from image-space to world-space. Set up a reverse transform as well.
                XMatrix imageSpaceToWorldSpace = ctx.ImageSpaceToWorldSpace;

                XMatrix worldSpaceToImageSpace = imageSpaceToWorldSpace;
                worldSpaceToImageSpace.Invert();

                ctx.graphics.MultiplyTransform(imageSpaceToWorldSpace);

                using (Maps.Rendering.RenderUtil.SaveState(ctx.graphics))
                {

                    //------------------------------------------------------------
                    // Explicit Clipping
                    //------------------------------------------------------------

                    if (ctx.clipPath != null)
                        ctx.graphics.IntersectClip(ctx.clipPath);

                    //ctx.styles.showPseudoRandomStars = true;
                    //------------------------------------------------------------
                    // Backgrounds
                    //------------------------------------------------------------

                    RectangleF galacticBounds = new RectangleF(-14598.67f, -23084.26f, 29234.1133f, 25662.4746f); // TODO: Don't hardcode
                    Rectangle galaxyImageRect = new Rectangle(-18257, -26234, 36551, 32462); // Chosen to match T5 pp.416

                    // This transforms the Linehan galactic structure to the Mikesh galactic structure
                    // See http://travellermap.blogspot.com/2009/03/galaxy-scale-mismatch.html
                    Matrix xformLinehanToMikesh = new Matrix(0.9181034f, 0.0f, 0.0f, 0.855192542f, 120.672432f, 86.34569f);
                    timers.Add(new Timer("prep"));

                    //------------------------------------------------------------
                    // Local background (Nebula)
                    //------------------------------------------------------------
                    #region nebula-background

                    // 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 (ctx.styles.useBackgroundImage && galacticBounds.IntersectsWith(ctx.tileRect))
                    {
                        // Image-space rendering, so save current context
                        using (RenderUtil.SaveState(ctx.graphics))
                        {
                            // Never fill outside the galaxy
                            ctx.graphics.IntersectClip(galacticBounds);

                            // Map back to image space so it scales/tiles nicely
                            ctx.graphics.MultiplyTransform(worldSpaceToImageSpace);

                            const float backgroundImageScale = 2.0f;

                            lock (s_backgroundImage)
                            {
                                // Scaled size of the background
                                double w = s_backgroundImage.PixelWidth * backgroundImageScale;
                                double h = s_backgroundImage.PixelHeight * backgroundImageScale;

                                // Offset of the background, relative to the canvas
                                double ox = (float)(-ctx.tileRect.Left * ctx.scale * Astrometrics.ParsecScaleX) % w;
                                double oy = (float)(-ctx.tileRect.Top * ctx.scale * Astrometrics.ParsecScaleY) % h;
                                if (ox > 0) ox -= w;
                                if (oy > 0) oy -= h;

                                // Number of copies needed to cover the canvas
                                int nx = 1 + (int)Math.Floor(ctx.tileSize.Width / w);
                                int ny = 1 + (int)Math.Floor(ctx.tileSize.Height / h);
                                if (ox + nx * w < ctx.tileSize.Width) nx += 1;
                                if (oy + ny * h < ctx.tileSize.Height) ny += 1;

                                for (int x = 0; x < nx; ++x)
                                {
                                    for (int y = 0; y < ny; ++y)
                                    {
                                        ctx.graphics.DrawImage(s_backgroundImage, ox + x * w, oy + y * h, w + 1, h + 1);
                                        //ctx.graphics.DrawRectangle( XPens.Orange, ox + x * w, oy + y * h, w, h );
                                    }
                                }
                            }
                        }
                    }
                    #endregion
                    timers.Add(new Timer("background (nebula)"));

                    //------------------------------------------------------------
                    // Deep background (Galaxy)
                    //------------------------------------------------------------
                    #region galaxy-background
                    if (ctx.styles.useGalaxyImage && ctx.styles.deepBackgroundOpacity > 0f)
                    {
                        using (RenderUtil.SaveState(ctx.graphics))
                        {
                            ctx.graphics.MultiplyTransform(xformLinehanToMikesh);
                            ImageHolder galaxyImage = ctx.styles.lightBackground ? s_galaxyImageGray : s_galaxyImage;
                            lock (galaxyImage)
                            {
                                RenderUtil.DrawImageAlpha(ctx.graphics, ctx.styles.deepBackgroundOpacity, galaxyImage, galaxyImageRect);
                            }
                        }
                    }
                    #endregion
                    timers.Add(new Timer("background (galaxy)"));

                    //------------------------------------------------------------
                    // Pseudo-Random Stars
                    //------------------------------------------------------------
                    #region pseudorandom-stars

                    if (ctx.styles.pseudoRandomStars.visible)
                    {
                        // Render pseudorandom stars based on the tile # and
                        // scale factor. Note that these are positioned in
                        // screen space, not world space.

                        //const int nStars = 75;
                        int nMinStars = ctx.tileSize.Width * ctx.tileSize.Height / 300;
                        int nStars = ctx.scale >= 1 ? nMinStars : (int)(nMinStars / ctx.scale);

                        // NOTE: For performance's sake, three different cases are considered:
                        // (1) Tile is entirely within charted space (most common) - just render
                        //     the pseudorandom stars into the tile
                        // (2) Tile intersects the galaxy bounds - render pseudorandom stars
                        //     into a texture, then fill the galaxy vector with it
                        // (3) Tile is entire outside the galaxy - don't render stars

                        using (RenderUtil.SaveState(ctx.graphics))
                        {
                            ctx.graphics.SmoothingMode = XSmoothingMode.HighQuality;
                            solidBrush.Color = ctx.styles.pseudoRandomStars.fillColor;

                            Random rand = new Random((((int)ctx.tileRect.Left) << 8) ^ (int)ctx.tileRect.Top);
                            for (int i = 0; i < nStars; i++)
                            {
                                float starX = (float)rand.NextDouble() * ctx.tileRect.Width + ctx.tileRect.X;
                                float starY = (float)rand.NextDouble() * ctx.tileRect.Height + ctx.tileRect.Y;
                                float d = (float)rand.NextDouble() * 2;

                                //ctx.graphics.DrawRectangle( fonts.foregroundBrush, starX, starY, (float)( d / ctx.scale * Astrometrics.ParsecScaleX ), (float)( d / ctx.scale * Astrometrics.ParsecScaleY ) );
                                ctx.graphics.DrawEllipse(solidBrush, starX, starY, (float)(d / ctx.scale * Astrometrics.ParsecScaleX), (float)(d / ctx.scale * Astrometrics.ParsecScaleY));
                            }
                        }
                    }
                    #endregion
                    timers.Add(new Timer("pseudorandom"));

                    //------------------------------------------------------------
                    // Rifts in Charted Space
                    //------------------------------------------------------------
                    #region rifts

                    if (ctx.styles.showRifts && ctx.styles.riftOpacity > 0f)
                    {
                        Rectangle riftImageRect;
                        riftImageRect = new Rectangle(-1374, -827, 2769, 1754); // Correct
                        lock (s_riftImage)
                        {
                            RenderUtil.DrawImageAlpha(ctx.graphics, ctx.styles.riftOpacity, s_riftImage, riftImageRect);
                        }
                    }
                    #endregion
                    timers.Add(new Timer("rifts"));

                    //------------------------------------------------------------
                    // April Fool's Day
                    //------------------------------------------------------------
                    #region april-fools

                    if (ctx.silly)
                    {
                        using (RenderUtil.SaveState(ctx.graphics))
                        {
                            // Render in image-space
                            ctx.graphics.MultiplyTransform(worldSpaceToImageSpace);

                            XImage sillyImage = ctx.styles.grayscale ? s_sillyImageGray : s_sillyImageColor;

                            lock (sillyImage)
                            {
                                ctx.graphics.DrawImage(sillyImage, 0, 0, ctx.tileSize.Width, ctx.tileSize.Height);
                            }
                        }
                        timers.Add(new Timer("silly"));
                    }

                    #endregion

                    //------------------------------------------------------------
                    // Macro: Borders object
                    //------------------------------------------------------------
                    #region macro-borders
                    if (ctx.styles.macroBorders.visible)
                    {
                        ctx.styles.macroBorders.pen.Apply(ref pen);
                        ctx.graphics.SmoothingMode = XSmoothingMode.AntiAlias;
                        foreach (var vec in borderFiles
                            .Select(file => ctx.resourceManager.GetXmlFileObject(file, typeof(VectorObject)))
                            .OfType<VectorObject>()
                            .Where(vec => (vec.MapOptions & ctx.options & MapOptions.BordersMask) != 0))
                        {
                            vec.Draw(ctx.graphics, ctx.tileRect, ctx.options, pen);
                        }

                    }
                    #endregion
                    timers.Add(new Timer("macro-borders"));

                    //------------------------------------------------------------
                    // Macro: Route object
                    //------------------------------------------------------------
                    #region macro-routes

                    if (ctx.styles.macroRoutes.visible)
                    {
                        ctx.styles.macroRoutes.pen.Apply(ref pen);
                        ctx.graphics.SmoothingMode = XSmoothingMode.AntiAlias;
                        foreach (var vec in routeFiles
                            .Select(file => ctx.resourceManager.GetXmlFileObject(file, typeof(VectorObject)))
                            .OfType<VectorObject>()
                            .Where(vec => (vec.MapOptions & ctx.options & MapOptions.BordersMask) != 0))
                        {
                            vec.Draw(ctx.graphics, ctx.tileRect, ctx.options, pen);
                        }
                    }
                    #endregion
                    timers.Add(new Timer("macro-routes"));

                    //------------------------------------------------------------
                    // Sector Grid
                    //------------------------------------------------------------
                    #region sector-grid

                    ctx.graphics.SmoothingMode = XSmoothingMode.HighSpeed;

                    if (ctx.styles.sectorGrid.visible)
                    {
                        const int gridSlop = 10;
                        ctx.styles.sectorGrid.pen.Apply(ref pen);

                        for (float h = ((float)(Math.Floor((ctx.tileRect.Left) / Astrometrics.SectorWidth) - 1) - Astrometrics.ReferenceSector.X) * Astrometrics.SectorWidth - Astrometrics.ReferenceHex.X; h <= ctx.tileRect.Right + Astrometrics.SectorWidth; h += Astrometrics.SectorWidth)
                            ctx.graphics.DrawLine(pen, h, ctx.tileRect.Top - gridSlop, h, ctx.tileRect.Bottom + gridSlop);

                        for (float v = ((float)(Math.Floor((ctx.tileRect.Top) / Astrometrics.SectorHeight) - 1) - Astrometrics.ReferenceSector.Y) * Astrometrics.SectorHeight - Astrometrics.ReferenceHex.Y; v <= ctx.tileRect.Bottom + Astrometrics.SectorHeight; v += Astrometrics.SectorHeight)
                            ctx.graphics.DrawLine(pen, ctx.tileRect.Left - gridSlop, v, ctx.tileRect.Right + gridSlop, v);
                    }

                    #endregion
                    timers.Add(new Timer("sector grid"));

                    //------------------------------------------------------------
                    // Subsector Grid
                    //------------------------------------------------------------
                    #region subsector-grid
                    ctx.graphics.SmoothingMode = XSmoothingMode.HighSpeed;
                    if (ctx.styles.subsectorGrid.visible)
                    {
                        const int gridSlop = 10;
                        ctx.styles.subsectorGrid.pen.Apply(ref pen);

                        int hmin = (int)Math.Floor(ctx.tileRect.Left / Astrometrics.SubsectorWidth) - 1 - Astrometrics.ReferenceSector.X,
                            hmax = (int)Math.Ceiling((ctx.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;
                            ctx.graphics.DrawLine(pen, h, ctx.tileRect.Top - gridSlop, h, ctx.tileRect.Bottom + gridSlop);
                        }

                        int vmin = (int)Math.Floor(ctx.tileRect.Top / Astrometrics.SubsectorHeight) - 1 - Astrometrics.ReferenceSector.Y,
                            vmax = (int)Math.Ceiling((ctx.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;
                            ctx.graphics.DrawLine(pen, ctx.tileRect.Left - gridSlop, v, ctx.tileRect.Right + gridSlop, v);
                        }
                    }
                    #endregion
                    timers.Add(new Timer("subsector grid"));

                    //------------------------------------------------------------
                    // Parsec Grid
                    //------------------------------------------------------------
                    #region parsec-grid
                    // TODO: Optimize - timers indicate this is slow
                    ctx.graphics.SmoothingMode = XSmoothingMode.HighQuality;
                    if (ctx.styles.parsecGrid.visible)
                    {
                        const int parsecSlop = 1;

                        int hx = (int)Math.Floor(ctx.tileRect.Left);
                        int hw = (int)Math.Ceiling(ctx.tileRect.Width);
                        int hy = (int)Math.Floor(ctx.tileRect.Top);
                        int hh = (int)Math.Ceiling(ctx.tileRect.Height);

                        ctx.styles.parsecGrid.pen.Apply(ref pen);

                        switch (ctx.styles.hexStyle)
                        {
                            case HexStyle.Square:
                                for (int px = hx - parsecSlop; px < hx + hw + parsecSlop; px++)
                                {
                                    float yOffset = ((px % 2) != 0) ? 0.0f : 0.5f;
                                    for (int py = hy - parsecSlop; py < hy + hh + parsecSlop; py++)
                                    {
                                        // TODO: use RenderUtil.(Square|Hex)Edges(X|Y) arrays
                                        const float inset = 0.1f;
                                        ctx.graphics.DrawRectangle(pen, px + inset, py + inset + yOffset, 1 - inset * 2, 1 - inset * 2);
                                    }
                                }
                                break;

                            case HexStyle.Hex:
                                XPoint[] points = new XPoint[4];
                                for (int px = hx - parsecSlop; px < hx + hw + parsecSlop; px++)
                                {
                                    double yOffset = ((px % 2) != 0) ? 0.0 : 0.5;
                                    for (int py = hy - parsecSlop; py < hy + hh + parsecSlop; py++)
                                    {
                                        points[0] = new XPoint(px + -RenderUtil.HEX_EDGE, py + 0.5 + yOffset);
                                        points[1] = new XPoint(px + RenderUtil.HEX_EDGE, py + 1.0 + yOffset);
                                        points[2] = new XPoint(px + 1.0 - RenderUtil.HEX_EDGE, py + 1.0 + yOffset);
                                        points[3] = new XPoint(px + 1.0 + RenderUtil.HEX_EDGE, py + 0.5 + yOffset);
                                        ctx.graphics.DrawLines(pen, points);
                                    }
                                }
                                break;
                            case HexStyle.None:
                                // none
                                break;
                        }

                        if (ctx.styles.numberAllHexes &&
                            ctx.styles.worldDetails.HasFlag(WorldDetails.Hex))
                        {
                            solidBrush.Color = ctx.styles.hexNumber.textColor;
                            for (int px = hx - parsecSlop; px < hx + hw + parsecSlop; px++)
                            {
                                double yOffset = ((px % 2) != 0) ? 0.0 : 0.5;
                                for (int py = hy - parsecSlop; py < hy + hh + parsecSlop; py++)
                                {
                                    Location loc = Astrometrics.CoordinatesToLocation(px + 1, py + 1);
                                    string hex;
                                    switch (ctx.styles.hexCoordinateStyle)
                                    {
                                        default:
                                        case Stylesheet.HexCoordinateStyle.Sector: hex = loc.HexString; break;
                                        case Stylesheet.HexCoordinateStyle.Subsector: hex = loc.SubsectorHexString; break;
                                    }
                                    using (RenderUtil.SaveState(ctx.graphics))
                                    {
                                        XMatrix matrix = new XMatrix();
                                        matrix.TranslatePrepend(px + 0.5f, py + yOffset);
                                        matrix.ScalePrepend(ctx.styles.hexContentScale / Astrometrics.ParsecScaleX, ctx.styles.hexContentScale / Astrometrics.ParsecScaleY);
                                        ctx.graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend);
                                        ctx.graphics.DrawString(hex, ctx.styles.hexNumber.Font, solidBrush, 0, 0, RenderUtil.StringFormatTopCenter);
                                    }
                                }
                            }
                        }
                    }
                    #endregion
                    timers.Add(new Timer("parsec grid"));

                    //------------------------------------------------------------
                    // Subsector Names
                    //------------------------------------------------------------
                    #region subsector-names

                    if (ctx.styles.subsectorNames.visible)
                    {
                        solidBrush.Color = ctx.styles.subsectorNames.textColor;
                        foreach (Sector sector in ctx.selector.Sectors)
                        {
                            for (int i = 0; i < 16; i++)
                            {
                                int ssx = i % 4;
                                int ssy = i / 4;

                                Subsector ss = sector[i];
                                if (ss == null || String.IsNullOrEmpty(ss.Name))
                                    continue;

                                Point center = sector.SubsectorCenter(i);
                                RenderUtil.DrawLabel(ctx.graphics, ss.Name, center, ctx.styles.subsectorNames.Font, solidBrush, ctx.styles.subsectorNames.textStyle);
                            }
                        }
                    }

                    #endregion
                    timers.Add(new Timer("subsector names"));

                    //------------------------------------------------------------
                    // Micro: Borders
                    //------------------------------------------------------------
                    #region micro-borders
                    if (ctx.styles.microBorders.visible)
                    {
                        if (ctx.styles.fillMicroBorders)
                            DrawMicroBorders(ctx, BorderLayer.Fill);
                        DrawMicroBorders(ctx, BorderLayer.Stroke);
                    }
                    #endregion
                    timers.Add(new Timer("micro-borders"));

                    //------------------------------------------------------------
                    // Micro: Routes
                    //------------------------------------------------------------
                    #region micro-routes

                    if (ctx.styles.microRoutes.visible)
                        DrawRoutes(ctx, fonts);

                    #endregion
                    timers.Add(new Timer("micro-routes"));

                    //------------------------------------------------------------
                    // Sector Names
                    //------------------------------------------------------------
                    #region sector-names

                    if (ctx.styles.showSomeSectorNames || ctx.styles.showAllSectorNames)
                    {
                        foreach (Sector sector in ctx.selector.Sectors
                            .Where(sector => ctx.styles.showAllSectorNames || (ctx.styles.showSomeSectorNames && sector.Selected))
                            .Where(sector => sector.Names.Any() || sector.Label != null))
                        {
                            solidBrush.Color = ctx.styles.sectorName.textColor;
                            string name = sector.Label ?? sector.Names[0].Text;

                            RenderUtil.DrawLabel(ctx.graphics, name, sector.Center, ctx.styles.sectorName.Font, solidBrush, ctx.styles.sectorName.textStyle);
                        }
                    }

                    #endregion
                    timers.Add(new Timer("sector names"));

                    //------------------------------------------------------------
                    // Mega: Galaxy-Scale Labels
                    //------------------------------------------------------------
                    #region mega-names
                    if (ctx.styles.megaNames.visible)
                    {
                        solidBrush.Color = ctx.styles.megaNames.textColor;
                        foreach (var label in megaLabels)
                        {
                            using (RenderUtil.SaveState(ctx.graphics))
                            {
                                XMatrix matrix = new XMatrix();
                                matrix.ScalePrepend(1.0f / Astrometrics.ParsecScaleX, 1.0f / Astrometrics.ParsecScaleY);
                                matrix.TranslatePrepend(label.position.X, label.position.Y);
                                ctx.graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend);

                                XFont font = label.minor ? ctx.styles.megaNames.SmallFont : ctx.styles.megaNames.Font;
                                XSize size = ctx.graphics.MeasureString(label.text, font);
                                ctx.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(ctx.graphics);
                                formatter.Alignment = XParagraphAlignment.Center;
                                formatter.DrawString(label.text, font, solidBrush, textBounds);
                            }
                        }
                    }
                    #endregion
                    timers.Add(new Timer("mega names"));

                    //------------------------------------------------------------
                    // Macro: Government / Rift / Route Names
                    //------------------------------------------------------------
                    #region government-rift-names
                    if (ctx.styles.macroNames.visible)
                    {
                        foreach (var vec in borderFiles
                            .Select(file => ctx.resourceManager.GetXmlFileObject(file, typeof(VectorObject)))
                            .OfType<VectorObject>()
                            .Where(vec => (vec.MapOptions & ctx.options & MapOptions.NamesMask) != 0))
                        {
                            bool major = vec.MapOptions.HasFlag(MapOptions.NamesMajor);
                            LabelStyle labelStyle = new LabelStyle();
                            labelStyle.Uppercase = major;
                            XFont font = major ? ctx.styles.macroNames.Font : ctx.styles.macroNames.SmallFont;
                            solidBrush.Color = major ? ctx.styles.macroNames.textColor : ctx.styles.macroNames.textHighlightColor;
                            vec.DrawName(ctx.graphics, ctx.tileRect, ctx.options, font, solidBrush, labelStyle);
                        }

                        foreach (var vec in riftFiles
                            .Select(file => ctx.resourceManager.GetXmlFileObject(file, typeof(VectorObject)))
                            .OfType<VectorObject>()
                            .Where(vec => (vec.MapOptions & ctx.options & MapOptions.NamesMask) != 0))
                        {
                            bool major = vec.MapOptions.HasFlag(MapOptions.NamesMajor);
                            LabelStyle labelStyle = new LabelStyle();
                            labelStyle.Rotation = 35;
                            labelStyle.Uppercase = major;
                            XFont font = major ? ctx.styles.macroNames.Font : ctx.styles.macroNames.SmallFont;
                            solidBrush.Color = major ? ctx.styles.macroNames.textColor : ctx.styles.macroNames.textHighlightColor;
                            vec.DrawName(ctx.graphics, ctx.tileRect, ctx.options, font, solidBrush, labelStyle);
                        }

                        if (ctx.styles.macroRoutes.visible)
                        {
                            foreach (var vec in routeFiles
                                .Select(file => ctx.resourceManager.GetXmlFileObject(file, typeof(VectorObject)))
                                .OfType<VectorObject>()
                                .Where(vec => (vec.MapOptions & ctx.options & MapOptions.NamesMask) != 0))
                            {
                                bool major = vec.MapOptions.HasFlag(MapOptions.NamesMajor);
                                LabelStyle labelStyle = new LabelStyle();
                                labelStyle.Uppercase = major;
                                XFont font = major ? ctx.styles.macroNames.Font : ctx.styles.macroNames.SmallFont;
                                solidBrush.Color = major ? ctx.styles.macroRoutes.textColor : ctx.styles.macroRoutes.textHighlightColor;
                                vec.DrawName(ctx.graphics, ctx.tileRect, ctx.options, font, solidBrush, labelStyle);
                            }
                        }

                        if (ctx.options.HasFlag(MapOptions.NamesMinor))
                        {
                            XFont font = ctx.styles.macroNames.MediumFont;
                            solidBrush.Color = ctx.styles.macroRoutes.textHighlightColor;
                            foreach (var label in labels)
                            {
                                using (RenderUtil.SaveState(ctx.graphics))
                                {
                                    XMatrix matrix = new XMatrix();
                                    matrix.ScalePrepend(1.0f / Astrometrics.ParsecScaleX, 1.0f / Astrometrics.ParsecScaleY);
                                    matrix.TranslatePrepend(label.position.X, label.position.Y);
                                    ctx.graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend);

                                    XSize size = ctx.graphics.MeasureString(label.text, font);
                                    ctx.graphics.TranslateTransform(-size.Width / 2, -size.Height / 2); // Center the text
                                    RectangleF textBounds = new RectangleF(0, 0, (float)size.Width, (float)size.Height * 2); // *2 or it gets cut off at high sizes
                                    XTextFormatter formatter = new XTextFormatter(ctx.graphics);
                                    formatter.Alignment = XParagraphAlignment.Center;
                                    formatter.DrawString(label.text, font, solidBrush, textBounds);
                                }
                            }

                        }
                    }

                    #endregion
                    timers.Add(new Timer("macro names"));

                    //------------------------------------------------------------
                    // Macro: Capitals & Home Worlds
                    //------------------------------------------------------------
                    #region capitals-homeworlds

                    if (ctx.styles.capitals.visible && (ctx.options & MapOptions.WorldsMask) != 0)
                    {
                        WorldObjectCollection worlds = ctx.resourceManager.GetXmlFileObject(@"~/res/Worlds.xml", typeof(WorldObjectCollection)) as WorldObjectCollection;
                        if (worlds != null)
                        {
                            solidBrush.Color = ctx.styles.capitals.textColor;
                            foreach (WorldObject world in worlds.Worlds.Where(world => (world.MapOptions & ctx.options) != 0))
                            {
                                world.Paint(ctx.graphics, ctx.tileRect, ctx.options, ctx.styles.capitals.fillColor,
                                    solidBrush, ctx.styles.macroNames.SmallFont);
                            }
                        }
                    }

                    #endregion
                    timers.Add(new Timer("macro worlds"));

                    //------------------------------------------------------------
                    // Micro: Border Labels & Explicit Labels
                    //------------------------------------------------------------
                    #region micro-border-labels

                    if (ctx.styles.showMicroNames)
                        DrawLabels(ctx, fonts);

                    #endregion
                    timers.Add(new Timer("micro-border labels"));
                }

                // End of clipping, so world names are not clipped in jumpmaps.

                //------------------------------------------------------------
                // Worlds
                //------------------------------------------------------------
                #region worlds
                if (ctx.styles.worlds.visible)
                {
                    // TODO: selector may be expensive
                    foreach (World world in ctx.selector.Worlds) { DrawWorld(ctx, fonts, world, WorldLayer.Background); }
                    foreach (World world in ctx.selector.Worlds) { DrawWorld(ctx, fonts, world, WorldLayer.Foreground); }
                }
                #endregion
                timers.Add(new Timer("worlds"));

                //------------------------------------------------------------
                // Unofficial
                //------------------------------------------------------------
                #region unofficial

                if (ctx.styles.dimUnofficialSectors && ctx.styles.worlds.visible)
                {
                    solidBrush.Color = Color.FromArgb(128, ctx.styles.backgroundColor);
                    foreach (Sector sector in ctx.selector.Sectors
                        .Where(sector => !sector.Tags.Contains("Official") && !sector.Tags.Contains("Preserve") && !sector.Tags.Contains("InReview")))
                        ctx.graphics.DrawRectangle(solidBrush, sector.Bounds);
                }

                #endregion

            #if SHOW_TIMING
                using( RenderUtil.SaveState( ctx.graphics ) )
                {
                    XFont font = new XFont( FontFamily.GenericSansSerif, 12, XFontStyle.Regular, new XPdfFontOptions(PdfSharp.Pdf.PdfFontEncoding.Unicode) );
                    ctx.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 )
                            {

                                ctx.graphics.DrawString( String.Format( "{0} {1}", Math.Round( ts.TotalMilliseconds ), s.label ), font, XBrushes.Black, cursorX + dx, cursorY + dy );
                            }
                        }
                        ctx.graphics.DrawString( String.Format("{0} {1}", Math.Round(ts.TotalMilliseconds), s.label), font, XBrushes.Yellow, cursorX, cursorY );
                        cursorY += 14;
                    }
                }
            #endif

            }
        }
Пример #4
0
    //    #region Realizing graphical state

    /// <summary>
    /// Initializes the default view transformation, i.e. the transformation from the user page
    /// space to the PDF page space.
    /// </summary>
    public void BeginContent(bool hacks4softmask)
    {
      if (!this.contentInitialized)
      {
        //this.defaultViewMatrix = XMatrix.Identity;
        //// Take TrimBox into account
        double pageHeight = Size.Height;
        //XPoint trimOffset = new XPoint();
        //if (this.page != null && this.page.TrimMargins.AreSet)
        //{
        //  pageHeight += this.page.TrimMargins.Top.Point + this.page.TrimMargins.Bottom.Point;
        //  trimOffset = new XPoint(this.page.TrimMargins.Left.Point, this.page.TrimMargins.Top.Point);
        //}

        //if (this.page != null && this.page.Elements.GetInteger("/Rotate") == 90)  // HACK for InDesign flyer
        //{
        //  defaultViewMatrix.RotatePrepend(90);
        //  defaultViewMatrix.ScalePrepend(1, -1);
        //}
        //else
        //{
        //  // Recall that the value of Height depends on Orientation.

        // Flip page horizontaly and mirror text.
        XMatrix defaultViewMatrix = new XMatrix();
        if (!hacks4softmask)
        {
          defaultViewMatrix.TranslatePrepend(0, pageHeight);
          defaultViewMatrix.ScalePrepend(0.75, -0.75);
        }
        //if (!trimOffset.IsEmpty)
        //{
        //  Debug.Assert(this.gfx.PageUnit == XGraphicsUnit.Point, "With TrimMargins set the page units must be Point. Ohter cases nyi.");
        //  defaultViewMatrix.TranslatePrepend(trimOffset.x, trimOffset.y);
        //}

        // Save initial graphic state
        WriteSaveState("BeginContent", null);
        // Set page transformation
        WriteRenderTransform(defaultViewMatrix);
        this.graphicsState.DefaultPageTransform = defaultViewMatrix;
        MultiplyTransform(defaultViewMatrix);
        if (!hacks4softmask)
          WriteLiteral("-100 Tz\n");
        this.contentInitialized = true;
      }
    }
    /// <summary>
    /// Draws the vertical Y axis.
    /// </summary>
    internal override void Draw()
    {
      AxisRendererInfo yari = ((ChartRendererInfo)this.rendererParms.RendererInfo).yAxisRendererInfo;

      double yMin = yari.MinimumScale;
      double yMax = yari.MaximumScale;
      double yMajorTick = yari.MajorTick;
      double yMinorTick = yari.MinorTick;

      XMatrix matrix = new XMatrix();  //XMatrix.Identity;
      matrix.TranslatePrepend(-yari.InnerRect.X, yMax);
      matrix.Scale(1, yari.InnerRect.Height / (yMax - yMin), XMatrixOrder.Append);
      matrix.ScalePrepend(1, -1); // mirror horizontal
      matrix.Translate(yari.InnerRect.X, yari.InnerRect.Y, XMatrixOrder.Append);

      // Draw axis.
      // First draw tick marks, second draw axis.
      double majorTickMarkStart = 0, majorTickMarkEnd = 0,
             minorTickMarkStart = 0, minorTickMarkEnd = 0;
      GetTickMarkPos(yari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd);

      XGraphics gfx = this.rendererParms.Graphics;
      LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, yari.LineFormat);
      LineFormatRenderer minorTickMarkLineFormat = new LineFormatRenderer(gfx, yari.MinorTickMarkLineFormat);
      LineFormatRenderer majorTickMarkLineFormat = new LineFormatRenderer(gfx, yari.MajorTickMarkLineFormat);
      XPoint[] points = new XPoint[2];

      // Draw minor tick marks.
      if (yari.MinorTickMark != TickMarkType.None)
      {
        for (double y = yMin + yMinorTick; y < yMax; y += yMinorTick)
        {
          points[0].X = minorTickMarkStart;
          points[0].Y = y;
          points[1].X = minorTickMarkEnd;
          points[1].Y = y;
          matrix.TransformPoints(points);
          minorTickMarkLineFormat.DrawLine(points[0], points[1]);
        }
      }

      double lineSpace = yari.TickLabelsFont.GetHeight(gfx);
      int cellSpace = yari.TickLabelsFont.FontFamily.GetLineSpacing(yari.TickLabelsFont.Style);
      double xHeight = yari.TickLabelsFont.Metrics.XHeight;

      XSize labelSize = new XSize(0, 0);
      labelSize.Height = lineSpace * xHeight / cellSpace;

      int countTickLabels = (int)((yMax - yMin) / yMajorTick) + 1;
      for (int i = 0; i < countTickLabels; ++i)
      {
        double y = yMin + yMajorTick * i;
        string str = y.ToString(yari.TickLabelsFormat);

        labelSize.Width = gfx.MeasureString(str, yari.TickLabelsFont).Width;

        // Draw major tick marks.
        if (yari.MajorTickMark != TickMarkType.None)
        {
          labelSize.Width += yari.MajorTickMarkWidth * 1.5;
          points[0].X = majorTickMarkStart;
          points[0].Y = y;
          points[1].X = majorTickMarkEnd;
          points[1].Y = y;
          matrix.TransformPoints(points);
          majorTickMarkLineFormat.DrawLine(points[0], points[1]);
        }
        else
          labelSize.Width += SpaceBetweenLabelAndTickmark;

        // Draw label text.
        XPoint[] layoutText = new XPoint[1];
        layoutText[0].X = yari.InnerRect.X + yari.InnerRect.Width - labelSize.Width;
        layoutText[0].Y = y;
        matrix.TransformPoints(layoutText);
        layoutText[0].Y += labelSize.Height / 2; // Center text vertically.
        gfx.DrawString(str, yari.TickLabelsFont, yari.TickLabelsBrush, layoutText[0]);
      }

      // Draw axis.
      if (yari.LineFormat != null && yari.LineFormat.Width > 0)
      {
        points[0].X = yari.InnerRect.X + yari.InnerRect.Width;
        points[0].Y = yMin;
        points[1].X = yari.InnerRect.X + yari.InnerRect.Width;
        points[1].Y = yMax;
        matrix.TransformPoints(points);
        if (yari.MajorTickMark != TickMarkType.None)
        {
          // yMax is at the upper side of the axis
          points[1].Y -= yari.LineFormat.Width / 2;
          points[0].Y += yari.LineFormat.Width / 2;
        }
        lineFormatRenderer.DrawLine(points[0], points[1]);
      }

      // Draw axis title
      if (yari.axisTitleRendererInfo != null && yari.axisTitleRendererInfo.AxisTitleText != "")
      {
        RendererParameters parms = new RendererParameters();
        parms.Graphics = gfx;
        parms.RendererInfo = yari;
        double width = yari.axisTitleRendererInfo.Width;
        yari.axisTitleRendererInfo.Rect = yari.InnerRect;
        yari.axisTitleRendererInfo.Width = width;
        AxisTitleRenderer atr = new AxisTitleRenderer(parms);
        atr.Draw();
      }
    }
Пример #6
0
        public void Fill(XGraphics graphics, RectangleF rect, Brush fillBrush)
        {
            if (graphics == null)
                throw new ArgumentNullException("graphics");

            RectangleF bounds = TransformedBounds;

            if (bounds.IntersectsWith(rect))
            {
                XGraphicsPath path = Path;

                using (RenderUtil.SaveState(graphics))
                {
                    XMatrix matrix = new XMatrix();
                    matrix.ScalePrepend(ScaleX, ScaleY);
                    matrix.TranslatePrepend(-OriginX, -OriginY);
                    graphics.MultiplyTransform(matrix);
                    graphics.DrawPath(fillBrush, path);
                }
            }
        }
Пример #7
0
        private void DrawStars(World world)
        {
            using (RenderUtil.SaveState(graphics))
            {
                graphics.SmoothingMode = XSmoothingMode.AntiAlias;
                PointF center = Astrometrics.HexToCenter(world.Coordinates);

                XMatrix matrix = new XMatrix();
                matrix.TranslatePrepend(center.X, center.Y);
                matrix.ScalePrepend(styles.hexContentScale / Astrometrics.ParsecScaleX, styles.hexContentScale / Astrometrics.ParsecScaleY);
                graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend);

                // TODO: Proper stellar parsing
                List<string> ss = new List<string>();
                foreach (Match m in STELLAR_REGEX.Matches(world.Stellar))
                {
                    ss.Add(m.Value);
                }

                int i = 0;
                foreach (var props in ss.Select(s => StellarRendering.star2props(s)).OrderByDescending(p => p.radius)) {
                    solidBrush.Color = props.color;
                    PointF offset = StellarRendering.Offset(i++);
                    const float offsetScale = 0.3f;
                    float r = 0.15f * props.radius;
                    graphics.DrawEllipse(solidBrush, offset.X * offsetScale - r, offset.Y * offsetScale - r, r*2, r*2);
                }
            }
        }
Пример #8
0
 /// <summary>
 /// Applies the specified scaling operation to the transformation matrix of this object
 /// in the specified order.
 /// </summary>
 public void ScaleTransform(double scaleXY, XMatrixOrder order)
 {
   //XMatrix matrix = this.transform;
   //matrix.Scale(scaleXY, scaleXY, order);
   //Transform = matrix;
   XMatrix matrix = new XMatrix();  //XMatrix.Identity;
   matrix.ScalePrepend(scaleXY, scaleXY);
   AddTransform(matrix, order);
 }
Пример #9
0
        private void DrawMacroNames()
        {
            foreach (var vec in borderFiles
                .Select(file => resourceManager.GetXmlFileObject(file, typeof(VectorObject)))
                .OfType<VectorObject>()
                .Where(vec => (vec.MapOptions & options & MapOptions.NamesMask) != 0))
            {
                bool major = vec.MapOptions.HasFlag(MapOptions.NamesMajor);
                LabelStyle labelStyle = new LabelStyle();
                labelStyle.Uppercase = major;
                XFont font = major ? styles.macroNames.Font : styles.macroNames.SmallFont;
                solidBrush.Color = major ? styles.macroNames.textColor : styles.macroNames.textHighlightColor;
                vec.DrawName(graphics, tileRect, font, solidBrush, labelStyle);
            }

            foreach (var vec in riftFiles
                .Select(file => resourceManager.GetXmlFileObject(file, typeof(VectorObject)))
                .OfType<VectorObject>()
                .Where(vec => (vec.MapOptions & options & MapOptions.NamesMask) != 0))
            {
                bool major = vec.MapOptions.HasFlag(MapOptions.NamesMajor);
                LabelStyle labelStyle = new LabelStyle();
                labelStyle.Rotation = 35;
                labelStyle.Uppercase = major;
                XFont font = major ? styles.macroNames.Font : styles.macroNames.SmallFont;
                solidBrush.Color = major ? styles.macroNames.textColor : styles.macroNames.textHighlightColor;
                vec.DrawName(graphics, tileRect, font, solidBrush, labelStyle);
            }

            if (styles.macroRoutes.visible)
            {
                foreach (var vec in routeFiles
                    .Select(file => resourceManager.GetXmlFileObject(file, typeof(VectorObject)))
                    .OfType<VectorObject>()
                    .Where(vec => (vec.MapOptions & options & MapOptions.NamesMask) != 0))
                {
                    bool major = vec.MapOptions.HasFlag(MapOptions.NamesMajor);
                    LabelStyle labelStyle = new LabelStyle();
                    labelStyle.Uppercase = major;
                    XFont font = major ? styles.macroNames.Font : styles.macroNames.SmallFont;
                    solidBrush.Color = major ? styles.macroRoutes.textColor : styles.macroRoutes.textHighlightColor;
                    vec.DrawName(graphics, tileRect, font, solidBrush, labelStyle);
                }
            }

            if (options.HasFlag(MapOptions.NamesMinor))
            {
                XFont font = styles.macroNames.MediumFont;
                solidBrush.Color = styles.macroRoutes.textHighlightColor;
                foreach (var label in labels)
                {
                    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);

                        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, (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);
                    }
                }

            }
        }
Пример #10
0
        private void DrawParsecGrid()
        {
            const int parsecSlop = 1;

            int hx = (int)Math.Floor(tileRect.Left);
            int hw = (int)Math.Ceiling(tileRect.Width);
            int hy = (int)Math.Floor(tileRect.Top);
            int hh = (int)Math.Ceiling(tileRect.Height);

            styles.parsecGrid.pen.Apply(ref pen);

            switch (styles.hexStyle)
            {
                case HexStyle.Square:
                    for (int px = hx - parsecSlop; px < hx + hw + parsecSlop; px++)
                    {
                        float yOffset = ((px % 2) != 0) ? 0.0f : 0.5f;
                        for (int py = hy - parsecSlop; py < hy + hh + parsecSlop; py++)
                        {
                            // TODO: use RenderUtil.(Square|Hex)Edges(X|Y) arrays
                            const float inset = 0.1f;
                            graphics.DrawRectangle(pen, px + inset, py + inset + yOffset, 1 - inset * 2, 1 - inset * 2);
                        }
                    }
                    break;

                case HexStyle.Hex:
                    XPoint[] points = new XPoint[4];
                    for (int px = hx - parsecSlop; px < hx + hw + parsecSlop; px++)
                    {
                        double yOffset = ((px % 2) != 0) ? 0.0 : 0.5;
                        for (int py = hy - parsecSlop; py < hy + hh + parsecSlop; py++)
                        {
                            points[0] = new XPoint(px + -RenderUtil.HEX_EDGE, py + 0.5 + yOffset);
                            points[1] = new XPoint(px + RenderUtil.HEX_EDGE, py + 1.0 + yOffset);
                            points[2] = new XPoint(px + 1.0 - RenderUtil.HEX_EDGE, py + 1.0 + yOffset);
                            points[3] = new XPoint(px + 1.0 + RenderUtil.HEX_EDGE, py + 0.5 + yOffset);
                            graphics.DrawLines(pen, points);
                        }
                    }
                    break;
                case HexStyle.None:
                    // none
                    break;
            }

            if (styles.numberAllHexes &&
                styles.worldDetails.HasFlag(WorldDetails.Hex))
            {
                solidBrush.Color = styles.hexNumber.textColor;
                for (int px = hx - parsecSlop; px < hx + hw + parsecSlop; px++)
                {
                    double yOffset = ((px % 2) != 0) ? 0.0 : 0.5;
                    for (int py = hy - parsecSlop; py < hy + hh + parsecSlop; py++)
                    {
                        Location loc = Astrometrics.CoordinatesToLocation(px + 1, py + 1);
                        string hex;
                        switch (styles.hexCoordinateStyle)
                        {
                            default:
                            case Stylesheet.HexCoordinateStyle.Sector: hex = loc.HexString; break;
                            case Stylesheet.HexCoordinateStyle.Subsector: hex = loc.SubsectorHexString; break;
                        }
                        using (RenderUtil.SaveState(graphics))
                        {
                            XMatrix matrix = new XMatrix();
                            matrix.TranslatePrepend(px + 0.5f, py + yOffset);
                            matrix.ScalePrepend(styles.hexContentScale / Astrometrics.ParsecScaleX, styles.hexContentScale / Astrometrics.ParsecScaleY);
                            graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend);
                            graphics.DrawString(hex, styles.hexNumber.Font, solidBrush, 0, 0, RenderUtil.StringFormatTopCenter);
                        }
                    }
                }
            }
        }
Пример #11
0
        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
            }
        }
Пример #12
0
        public RenderContext(ResourceManager resourceManager, Selector selector, RectangleF tileRect,
            double scale, MapOptions options, Stylesheet styles, Size tileSize)
        {
            this.resourceManager = resourceManager;
            this.selector = selector;
            this.tileRect = tileRect;
            this.scale = scale;
            this.options = options;
            this.styles = styles;
            this.tileSize = tileSize;

            XMatrix m = new XMatrix();
            m.TranslatePrepend((float)(-tileRect.Left * scale * Astrometrics.ParsecScaleX), (float)(-tileRect.Top * scale * Astrometrics.ParsecScaleY));
            m.ScalePrepend((float)scale * Astrometrics.ParsecScaleX, (float)scale * Astrometrics.ParsecScaleY);
            imageSpaceToWorldSpace = m;
            m.Invert();
            worldSpaceToImageSpace = m;
        }
    /// <summary>
    /// Writes a Glyphs to the content stream.
    /// </summary>
    private void WriteGlyphs(Glyphs glyphs)
    {
      WriteSaveState("begin Glyphs", glyphs.Name);

      // Transform also affects clipping and opacity mask
      bool transformed = glyphs.RenderTransform != null;
      if (transformed)
        WriteRenderTransform(glyphs.RenderTransform);

      bool clipped = glyphs.Clip != null;
      if (clipped)
        WriteClip(glyphs.Clip);

      if (glyphs.Opacity < 1)
        MultiplyOpacity(glyphs.Opacity);

      if (glyphs.OpacityMask != null)
        WriteOpacityMask(glyphs.OpacityMask);

      XMatrix textMatrix = new XMatrix();

      textMatrix.TranslatePrepend(glyphs.OriginX, glyphs.OriginY);
      glyphs.OriginX = glyphs.OriginY = 0; // HACK: do not change model

      double emSize = glyphs.FontRenderingEmSize;
      textMatrix.ScalePrepend(glyphs.FontRenderingEmSize);
      glyphs.FontRenderingEmSize = 1; // HACK: do not change model


      bool boldSimulation = (glyphs.StyleSimulations & StyleSimulations.BoldSimulation) == StyleSimulations.BoldSimulation;

      // just a draft...
      if (boldSimulation)
      {
        boldSimulation = true;

        // draw black stroke if it is not a solid color brush
        XColor color = XColor.FromArgb(0, 0, 0);
        if (glyphs.Fill is SolidColorBrush)
        {
          SolidColorBrush brush = glyphs.Fill as SolidColorBrush;
          color = brush.Color;
        }
        WriteLiteral(String.Format(CultureInfo.InvariantCulture, "{0:0.###} {1:0.###} {2:0.###}  RG\n", color.R / 255.0, color.G / 255.0, color.B / 255.0));
        WriteLiteral("{0:0.###} w\n", emSize / 50);
      }

      if ((glyphs.StyleSimulations & StyleSimulations.ItalicSimulation) == StyleSimulations.ItalicSimulation)
      {
        textMatrix.SkewPrepend(-20, 0);
      }

      XForm xform = null;
      XImage ximage = null;
      RealizeFill(glyphs.Fill, ref xform, ref ximage);
      RealizeFont(glyphs);

      if (boldSimulation)
        WriteLiteral("2 Tr\n", 1);

      double x = glyphs.OriginX;
      double y = glyphs.OriginY;


      //switch (format.Alignment)
      //{
      //  case XStringAlignment.Near:
      //    // nothing to do
      //    break;

      //  case XStringAlignment.Center:
      //    x += (rect.Width - width) / 2;
      //    break;

      //  case XStringAlignment.Far:
      //    x += rect.Width - width;
      //    break;
      //}

      PdfFont realizedFont = this.graphicsState.realizedFont;
      Debug.Assert(realizedFont != null);
      realizedFont.AddChars(glyphs.UnicodeString);

      OpenTypeDescriptor descriptor = realizedFont.FontDescriptor.descriptor;

      //if (bold && !descriptor.IsBoldFace)
      //{
      //  // TODO: emulate bold by thicker outline
      //}

      //if (italic && !descriptor.IsBoldFace)
      //{
      //  // TODO: emulate italic by shearing transformation
      //}

#if true
      string s2 = "";
      string s = glyphs.UnicodeString;
      if (!String.IsNullOrEmpty(s))
      {
        int length = s.Length;
        for (int idx = 0; idx < length; idx++)
        {
          char ch = s[idx];
          int glyphID = 0;
          if (descriptor.fontData.cmap.symbol)
          {
            glyphID = (int)ch + (descriptor.fontData.os2.usFirstCharIndex & 0xFF00);
            glyphID = descriptor.CharCodeToGlyphIndex((char)glyphID);
          }
          else
            glyphID = descriptor.CharCodeToGlyphIndex(ch);
          s2 += (char)glyphID;
        }
      }
      s = s2;
#endif

      byte[] bytes = PdfEncoders.RawUnicodeEncoding.GetBytes(s);
      bytes = PdfEncoders.FormatStringLiteral(bytes, true, false, true, null);
      string text = PdfEncoders.RawEncoding.GetString(bytes);
      if (glyphs.IsSideways)
      {
        textMatrix.RotateAtPrepend(-90, new XPoint(x, y));
        XPoint pos = new XPoint(x, y);
        AdjustTextMatrix(ref pos);
        //WriteTextTransform(textMatrix);
        WriteLiteral("{0} Tj\n", text);
      }
      else
      {
#if true
        //if (glyphs.BidiLevel % 2 == 1)
        //  WriteLiteral("-1 Tc\n");

        if (!textMatrix.IsIdentity)
          WriteTextTransform(textMatrix);

        WriteGlyphsInternal(glyphs, null);
#else
        XPoint pos = new XPoint(x, y);
        AdjustTextMatrix(ref pos);
        WriteLiteral("{0:0.###} {1:0.###} Td {2} Tj\n", pos.x, pos.y, text);
        //PdfEncoders.ToStringLiteral(s, PdfStringEncoding.RawEncoding, null));
#endif
      }
      WriteRestoreState("end Glyphs", glyphs.Name);
    }
Пример #14
0
    /// <summary>
    /// Saves a graphics container with the current state of this XGraphics and 
    /// opens and uses a new graphics container.
    /// </summary>
    public XGraphicsContainer BeginContainer(XRect dstrect, XRect srcrect, XGraphicsUnit unit)
    {
      // TODO: unit
      if (unit != XGraphicsUnit.Point)
        throw new ArgumentException("The current implementation supports XGraphicsUnit.Point only.", "unit");

      XGraphicsContainer xContainer = null;
#if GDI
      if (this.targetContext == XGraphicTargetContext.GDI)
        xContainer = new XGraphicsContainer(this.gfx.Save());
#endif
#if WPF
      if (this.targetContext == XGraphicTargetContext.WPF)
        xContainer = new XGraphicsContainer();
#endif
      InternalGraphicsState iState = new InternalGraphicsState(this, xContainer);
      iState.Transform = this.transform;

      this.gsStack.Push(iState);

      if (this.renderer != null)
        this.renderer.BeginContainer(xContainer, dstrect, srcrect, unit);

      XMatrix matrix = new XMatrix();  //XMatrix.Identity;
#if true
      double scaleX = dstrect.Width / srcrect.Width;
      double scaleY = dstrect.Height / srcrect.Height;
      matrix.TranslatePrepend(-srcrect.X, -srcrect.Y);
      matrix.ScalePrepend(scaleX, scaleY);
      matrix.TranslatePrepend(dstrect.X / scaleX, dstrect.Y / scaleY);
#else
      matrix.Translate(-dstrect.X, -dstrect.Y);
      matrix.Scale(dstrect.Width / srcrect.Width, dstrect.Height / srcrect.Height);
      matrix.Translate(srcrect.X, srcrect.Y);
#endif
      AddTransform(matrix, XMatrixOrder.Prepend);

      return xContainer;
    }
Пример #15
0
        public void Draw(XGraphics graphics, RectangleF rect, MapOptions options, XPen pen)
        {
            if (graphics == null)
                throw new ArgumentNullException("graphics");

            RectangleF bounds = TransformedBounds;

            //graphics.DrawRectangle( new XPen(XColors.Yellow, 1), bounds.X, bounds.Y, bounds.Width, bounds.Height );

            if (bounds.IntersectsWith(rect))
            {
                XGraphicsPath path = Path;
                using (RenderUtil.SaveState(graphics))
                {
                    XMatrix matrix = new XMatrix();
                    matrix.ScalePrepend(ScaleX, ScaleY);
                    matrix.TranslatePrepend(-OriginX, -OriginY);
                    graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend);
                    graphics.DrawPath(pen, path);
                }
            }
        }
Пример #16
0
 /// <summary>
 /// Applies the specified scaling operation to the transformation matrix of this object by 
 /// prepending it to the object's transformation matrix.
 /// </summary>
 public void ScaleTransform(double scaleXY)
 {
   //ScaleTransform(scaleXY, scaleXY, XMatrixOrder.Prepend);
   XMatrix matrix = new XMatrix();  //XMatrix.Identity;
   matrix.ScalePrepend(scaleXY, scaleXY);
   AddTransform(matrix, XMatrixOrder.Prepend);
 }
Пример #17
0
        public void DrawName(XGraphics graphics, RectangleF rect, MapOptions options, XFont font, XBrush textBrush, LabelStyle labelStyle)
        {
            if (graphics == null)
                throw new ArgumentNullException("graphics");

            RectangleF bounds = TransformedBounds;

            if (bounds.IntersectsWith(rect))
            {
                if (Name != null)
                {
                    string str = Name;
                    if (labelStyle.Uppercase)
                        str = str.ToUpperInvariant();

                    PointF pos = NamePosition;// PointF( bounds.Left + bounds.Width / 2, bounds.Top + bounds.Height / 2 );

                    using (RenderUtil.SaveState(graphics))
                    {
                        XMatrix matrix = new XMatrix();
                        matrix.TranslatePrepend(pos.X, pos.Y);
                        matrix.ScalePrepend(1.0f / Astrometrics.ParsecScaleX, 1.0f / Astrometrics.ParsecScaleY);
                        matrix.RotatePrepend(-labelStyle.Rotation); // Rotate it
                        graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend);

                        XSize size = graphics.MeasureString(str, font);
                        graphics.TranslateTransform(-size.Width / 2, -size.Height / 2); // Center the text
                        RectangleF textBounds = new RectangleF(0, 0, (float)size.Width, (float)size.Height * 2); // *2 or it gets cut off at high sizes

                        XTextFormatter tf = new XTextFormatter(graphics);
                        tf.Alignment = XParagraphAlignment.Center;
                        tf.DrawString(str, font, textBrush, textBounds);
                    }
                }
            }
        }
Пример #18
0
    /// <summary>
    /// Internal setup.
    /// </summary>
    void Initialize()
    {
      this.pageOrigin = new XPoint();
      XMatrix matrix = new XMatrix();  //XMatrix.Identity;

      double pageHeight = this.pageSize.height;
      PdfPage targetPage = PdfPage;
      XPoint trimOffset = new XPoint();
      if (targetPage != null && targetPage.TrimMargins.AreSet)
      {
        pageHeight += targetPage.TrimMargins.Top.Point + targetPage.TrimMargins.Bottom.Point;
        trimOffset = new XPoint(targetPage.TrimMargins.Left.Point, targetPage.TrimMargins.Top.Point);
      }

#if GDI
      if (this.targetContext == XGraphicTargetContext.GDI)
      {
        if (this.gfx != null)
          matrix = (XMatrix)gfx.Transform;

        if (this.pageUnit != XGraphicsUnit.Point)
        {
          switch (this.pageUnit)
          {
            case XGraphicsUnit.Inch:
              matrix.ScalePrepend(XUnit.InchFactor);
              break;

            case XGraphicsUnit.Millimeter:
              matrix.ScalePrepend(XUnit.MillimeterFactor);
              break;

            case XGraphicsUnit.Centimeter:
              matrix.ScalePrepend(XUnit.CentimeterFactor);
              break;

            case XGraphicsUnit.Presentation:
              matrix.ScalePrepend(XUnit.PresentationFactor);
              break;
          }
        }
      }
#endif
#if WPF
      if (this.targetContext == XGraphicTargetContext.WPF)
      {
        if (this.pageUnit != XGraphicsUnit.Presentation)
        {
          switch (this.pageUnit)
          {
            case XGraphicsUnit.Point:
              matrix.ScalePrepend(XUnit.PointFactorWpf);
              break;

            case XGraphicsUnit.Inch:
              matrix.ScalePrepend(XUnit.InchFactorWpf);
              break;

            case XGraphicsUnit.Millimeter:
              matrix.ScalePrepend(XUnit.MillimeterFactorWpf);
              break;

            case XGraphicsUnit.Centimeter:
              matrix.ScalePrepend(XUnit.CentimeterFactorWpf);
              break;
          }
          if (!matrix.IsIdentity)
          {
#if !SILVERLIGHT
            MatrixTransform transform = new MatrixTransform((System.Windows.Media.Matrix)matrix);
            dc.PushTransform(transform);
#else
            MatrixTransform transform2 = new MatrixTransform();
            transform2.Matrix = (System.Windows.Media.Matrix)matrix;
            dc.PushTransform(transform2);
#endif
          }
        }
      }
#endif
      if (this.pageDirection == XPageDirection.Upwards)
        matrix.Prepend(new XMatrix(1, 0, 0, -1, 0, pageHeight));

      if (trimOffset != new XPoint())
        matrix.TranslatePrepend(trimOffset.x, trimOffset.y);

      this.defaultViewMatrix = matrix;
      this.transform = new XMatrix();  //XMatrix.Identity;
    }
Пример #19
0
        public static void DrawLabel(XGraphics g, string text, PointF labelPos, XFont font, XBrush brush, LabelStyle labelStyle)
        {
            using (RenderUtil.SaveState(g))
            {
                XTextFormatter tf = new XTextFormatter(g);
                tf.Alignment = XParagraphAlignment.Center;

                XMatrix matrix = new XMatrix();
                matrix.TranslatePrepend(labelPos.X, labelPos.Y);
                matrix.ScalePrepend(1.0f / Astrometrics.ParsecScaleX, 1.0f / Astrometrics.ParsecScaleY);

                if (labelStyle.Uppercase)
                    text = text.ToUpper();
                if (labelStyle.Wrap)
                    text = text.Replace(' ', '\n');

                matrix.TranslatePrepend(labelStyle.Translation.X, labelStyle.Translation.Y);
                matrix.RotatePrepend(labelStyle.Rotation);
                matrix.ScalePrepend(labelStyle.Scale.Width, labelStyle.Scale.Height);
                g.MultiplyTransform(matrix, XMatrixOrder.Prepend);

                XSize size = g.MeasureString(text, font);
                size.Width *= 2; // prevent cut-off e.g. when rotated
                XRect bounds = new XRect(-size.Width / 2, -size.Height / 2, size.Width, size.Height);
                tf.DrawString(text, font, brush, bounds);
            }
        }