Beispiel #1
0
        public static void ParseOptions(HttpRequest request, IDictionary<string, Object> queryDefaults, ref MapOptions options, ref Stylesheet.Style style)
        {
            options = (MapOptions)GetIntOption(request, "options", queryDefaults, (int)options);

#if LEGACY_STYLES
            // Handle deprecated/legacy options bits for selecting style
            style =
                (options & MapOptions.StyleMaskDeprecated) == MapOptions.PrintStyleDeprecated ? Stylesheet.Style.Atlas :
                (options & MapOptions.StyleMaskDeprecated) == MapOptions.CandyStyleDeprecated ? Stylesheet.Style.Candy :
                Stylesheet.Style.Poster;
#endif // LEGACY_STYLES

            if (HasOption(request, "style", queryDefaults))
            {
                switch (GetStringOption(request, "style", queryDefaults).ToLowerInvariant())
                {
                    case "poster": style = Stylesheet.Style.Poster; break;
                    case "atlas": style = Stylesheet.Style.Atlas; break;
                    case "print": style = Stylesheet.Style.Print; break;
                    case "candy": style = Stylesheet.Style.Candy; break;
                    case "draft": style = Stylesheet.Style.Draft; break;
                    case "fasa": style = Stylesheet.Style.FASA; break;
                }
            }
        }
Beispiel #2
0
            public override void Process()
            {
                ResourceManager resourceManager = new ResourceManager(context.Server);

                MapOptions options = MapOptions.SectorGrid | MapOptions.BordersMajor | MapOptions.NamesMajor | MapOptions.NamesMinor;
                Stylesheet.Style style = Stylesheet.Style.Poster;
                ParseOptions(ref options, ref style);

                double x = GetDoubleOption("x", 0);
                double y = GetDoubleOption("y", 0);
                double scale = Util.Clamp(GetDoubleOption("scale", 0), MinScale, MaxScale);
                int width = Util.Clamp(GetIntOption("w", NormalTileWidth), MinDimension, MaxDimension);
                int height = Util.Clamp(GetIntOption("h", NormalTileHeight), MinDimension, MaxDimension);

                Size tileSize = new Size(width, height);

                RectangleF tileRect = new RectangleF();
                tileRect.X = (float)(x * tileSize.Width / (scale * Astrometrics.ParsecScaleX));
                tileRect.Y = (float)(y * tileSize.Height / (scale * Astrometrics.ParsecScaleY));
                tileRect.Width = (float)(tileSize.Width / (scale * Astrometrics.ParsecScaleX));
                tileRect.Height = (float)(tileSize.Height / (scale * Astrometrics.ParsecScaleY));

                DateTime dt = DateTime.Now;
                bool silly = (Math.Abs((int)x % 2) == Math.Abs((int)y % 2)) && (dt.Month == 4 && dt.Day == 1);
                silly = GetBoolOption("silly", silly);

                Selector selector = new RectSelector(SectorMap.ForMilieu(resourceManager, GetStringOption("milieu")), resourceManager, tileRect);
                Stylesheet styles = new Stylesheet(scale, options, style);
                RenderContext ctx = new RenderContext(resourceManager, selector, tileRect, scale, options, styles, tileSize);
                ctx.Silly = silly;
                ctx.ClipOutsectorBorders = true;
                ProduceResponse(context, "Tile", ctx, tileSize);
            }
        public const double MaxScale = 512; // Math.Pow(2, 9);

        protected void ParseOptions(ref MapOptions options, ref Stylesheet.Style style)
        {
            options = (MapOptions)GetIntOption("options", (int)options);

#if LEGACY_STYLES
            // Handle deprecated/legacy options bits for selecting style
            style =
                (options & MapOptions.StyleMaskDeprecated) == MapOptions.PrintStyleDeprecated ? Stylesheet.Style.Atlas :
                (options & MapOptions.StyleMaskDeprecated) == MapOptions.CandyStyleDeprecated ? Stylesheet.Style.Candy :
                Stylesheet.Style.Poster;
#endif // LEGACY_STYLES

            if (HasOption("style"))
            {
                switch (GetStringOption("style").ToLowerInvariant())
                {
                    case "poster": style = Stylesheet.Style.Poster; break;
                    case "atlas": style = Stylesheet.Style.Atlas; break;
                    case "print": style = Stylesheet.Style.Print; break;
                    case "candy": style = Stylesheet.Style.Candy; break;
                }
            }
        }
        private void Page_Load(object sender, System.EventArgs e)
        {
            if (!ServiceConfiguration.CheckEnabled("jumpmap", Response))
            {
                return;
            }

            // NOTE: This (re)initializes a static data structure used for
            // resolving names into sector locations, so needs to be run
            // before any other objects (e.g. Worlds) are loaded.
            ResourceManager resourceManager = new ResourceManager(Server, Cache);

            //
            // Jump
            //
            int jump = Util.Clamp(GetIntOption("jump", 6), 0, 12);

            //
            // Content & Coordinates
            //
            Selector selector;
            Location loc;
            if (Request.HttpMethod == "POST")
            {
                Sector sector;
                try
                {
                    sector = GetPostedSector();
                }
                catch (Exception ex)
                {
                    SendError(400, "Invalid request", ex.Message);
                    return;
                }

                if (sector == null)
                {
                    SendError(400, "Invalid request", "Either file or data must be supplied in the POST data.");
                    return;
                }

                int hex = GetIntOption("hex", Astrometrics.SectorCentralHex);
                loc = new Location(new Point(0, 0), hex);
                selector = new HexSectorSelector(resourceManager, sector, loc.HexLocation, jump);
            }
            else
            {
                SectorMap map = SectorMap.FromName(SectorMap.DefaultSetting, resourceManager);

                if (HasOption("sector") && HasOption("hex"))
                {
                    string sectorName = GetStringOption("sector");
                    int hex = GetIntOption("hex", 0);
                    loc = new Location(map.FromName(sectorName).Location, hex);
                }
                else if (HasOption("sx") && HasOption("sy") && HasOption("hx") && HasOption("hy"))
                {
                    int sx = GetIntOption("sx", 0);
                    int sy = GetIntOption("sy", 0);
                    int hx = GetIntOption("hx", 0);
                    int hy = GetIntOption("hy", 0);
                    loc = new Location(map.FromLocation(sx, sy).Location, hx * 100 + hy);
                }
                else if (HasOption("x") && HasOption("y"))
                {
                    loc = Astrometrics.CoordinatesToLocation(GetIntOption("x", 0), GetIntOption("y", 0));
                }
                else
                {
                    loc = new Location(map.FromName("Spinward Marches").Location, 1910);
                }
                selector = new HexSelector(map, resourceManager, loc, jump);
            }

            //
            // Scale
            //
            double scale = Util.Clamp(GetDoubleOption("scale", 64), MinScale, MaxScale);

            //
            // Options & Style
            //
            MapOptions options = MapOptions.BordersMajor | MapOptions.BordersMinor | MapOptions.ForceHexes;
            Stylesheet.Style style = Stylesheet.Style.Poster;
            ParseOptions(ref options, ref style);

            //
            // Border
            //
            bool border = GetBoolOption("border", defaultValue: true);

            //
            // Clip
            //
            bool clip = GetBoolOption("clip", defaultValue: true);

            //
            // What to render
            //

            RectangleF tileRect = new RectangleF();

            Point coords = Astrometrics.LocationToCoordinates(loc);
            tileRect.X = coords.X - jump - 1;
            tileRect.Width = jump + 1 + jump;
            tileRect.Y = coords.Y - jump - 1;
            tileRect.Height = jump + 1 + jump;

            // Account for jagged hexes
            tileRect.Y += (coords.X % 2 == 0) ? 0 : 0.5f;
            tileRect.Inflate(0.35f, 0.15f);

            Size tileSize = new Size((int)Math.Floor(tileRect.Width * scale * Astrometrics.ParsecScaleX), (int)Math.Floor(tileRect.Height * scale * Astrometrics.ParsecScaleY));

            // Construct clipping path
            List<Point> clipPath = new List<Point>(jump * 6 + 1);
            Point cur = coords;
            for (int i = 0; i < jump; ++i)
            {
                // Move J parsecs to the upper-left (start of border path logic)
                cur = Astrometrics.HexNeighbor(cur, 1);
            }
            clipPath.Add(cur);
            for (int dir = 0; dir < 6; ++dir)
            {
                for (int i = 0; i < jump; ++i)
                {
                    cur = Astrometrics.HexNeighbor(cur, (dir + 3) % 6); // Clockwise from upper left
                    clipPath.Add(cur);
                }
            }

            Stylesheet styles = new Stylesheet(scale, options, style);

            // If any names are showing, show them all
            if (styles.worldDetails.HasFlag(WorldDetails.KeyNames))
            {
                styles.worldDetails |= WorldDetails.AllNames;
            }

            // Compute path
            float[] edgeX, edgeY;
            RenderUtil.HexEdges(styles.microBorderStyle == MicroBorderStyle.Square ? PathUtil.PathType.Square : PathUtil.PathType.Hex,
                out edgeX, out edgeY);
            PointF[] boundingPathCoords;
            byte[] boundingPathTypes;
            PathUtil.ComputeBorderPath(clipPath, edgeX, edgeY, out boundingPathCoords, out boundingPathTypes);

            Render.RenderContext ctx = new Render.RenderContext();
            ctx.resourceManager = resourceManager;
            ctx.selector = selector;
            ctx.tileRect = tileRect;
            ctx.scale = scale;
            ctx.options = options;
            ctx.styles = styles;
            ctx.tileSize = tileSize;
            ctx.border = border;

            ctx.clipPath = clip ? new XGraphicsPath(boundingPathCoords, boundingPathTypes, XFillMode.Alternate) : null;
            ProduceResponse("Jump Map", ctx, tileSize, transparent: clip);
        }
        protected void BitmapResponse(Stylesheet styles, Bitmap bitmap, string mimeType)
        {
            // JPEG or PNG if not specified, based on style
            if (mimeType == null)
            {
                mimeType = styles.preferredMimeType;
            }

            Response.ContentType = mimeType;

            // Searching for a matching encoder
            ImageCodecInfo encoder = null;
            ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
            for (int i = 0; i < encoders.Length; ++i)
            {
                if (encoders[i].MimeType == Response.ContentType)
                {
                    encoder = encoders[i];
                    break;
                }
            }

            if (encoder != null)
            {
                EncoderParameters encoderParams;
                if (mimeType == MediaTypeNames.Image.Jpeg)
                {
                    encoderParams = new EncoderParameters(1);
                    encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)95);
                }
                else if (mimeType == Util.MediaTypeName_Image_Png)
                {
                    encoderParams = new EncoderParameters(1);
                    encoderParams.Param[0] = new EncoderParameter(Encoder.ColorDepth, 8);
                }
                else
                {
                    encoderParams = new EncoderParameters(0);
                }

                if (mimeType == Util.MediaTypeName_Image_Png)
                {
                    // PNG encoder is picky about streams - need to do an indirection
                    // http://www.west-wind.com/WebLog/posts/8230.aspx
                    using (var ms = new MemoryStream())
                    {
                        bitmap.Save(ms, encoder, encoderParams);
                        ms.WriteTo(Context.Response.OutputStream);
                    }
                }
                else
                {
                    bitmap.Save(Context.Response.OutputStream, encoder, encoderParams);
                }

                encoderParams.Dispose();
            }
            else
            {
                // Default to GIF if we can't find anything
                Response.ContentType = MediaTypeNames.Image.Gif;
                bitmap.Save(Context.Response.OutputStream, ImageFormat.Gif);
            }
        }
Beispiel #6
0
 public FontCache(Stylesheet sheet)
 {
     this.sheet = sheet;
 }
Beispiel #7
0
        public override void Process(System.Web.HttpContext context)
        {
            // NOTE: This (re)initializes a static data structure used for
            // resolving names into sector locations, so needs to be run
            // before any other objects (e.g. Worlds) are loaded.
            ResourceManager resourceManager = new ResourceManager(context.Server, context.Cache);

            Selector selector;
            RectangleF tileRect = new RectangleF();
            MapOptions options = MapOptions.SectorGrid | MapOptions.SubsectorGrid | MapOptions.BordersMajor | MapOptions.BordersMinor | MapOptions.NamesMajor | MapOptions.NamesMinor | MapOptions.WorldsCapitals | MapOptions.WorldsHomeworlds;
            Stylesheet.Style style = Stylesheet.Style.Poster;
            ParseOptions(context, ref options, ref style);
            string title;
            bool clipOutsectorBorders;

            if (HasOption(context, "x1") && HasOption(context, "x2") &&
                HasOption(context, "y1") && HasOption(context, "y2"))
            {
                // Arbitrary rectangle

                int x1 = GetIntOption(context, "x1", 0);
                int x2 = GetIntOption(context, "x2", 0);
                int y1 = GetIntOption(context, "y1", 0);
                int y2 = GetIntOption(context, "y2", 0);

                tileRect.X = Math.Min(x1, x2);
                tileRect.Y = Math.Min(y1, y2);
                tileRect.Width = Math.Max(x1, x2) - tileRect.X;
                tileRect.Height = Math.Max(y1, y2) - tileRect.Y;

                SectorMap map = SectorMap.FromName(SectorMap.DefaultSetting, resourceManager);
                selector = new RectSelector(map, resourceManager, tileRect);
                selector.Slop = false;

                tileRect.Offset(-1, -1);
                tileRect.Width += 1;
                tileRect.Height += 1;

                title = String.Format("Poster ({0},{1}) - ({2},{3})", x1, y1, x2, y2);
                clipOutsectorBorders = true;
            }
            else if (HasOption(context, "domain"))
            {
                string domain = GetStringOption(context, "domain");
                int x, y, w = 2, h = 2;
                switch (domain.ToLowerInvariant()) {
                    case "deneb": x = -4; y = -1; title = "Domain of Deneb"; break;
                    case "vland": x = -2; y = -1; title = "Domain of Vland";  break;
                    case "ilelish": x = -2; y = 1; title = "Domain of Ilelish";  break;
                    case "antares": x = 0; y = -2; title = "Domain of Antares";  break;
                    case "sylea": x = 0; y = 0; title = "Domain of Sylea";  break;
                    case "sol": x = 0; y = 2; title = "Domain of Sol";  break;
                    case "gateway": x = 2; y = 0; title = "Domain of Gateway"; break;

                        // And these aren't domains, but...
                    case "foreven": x = -6; y = -1; title = "Land Grab / Foreven"; break;
                    case "imperium": x = -4; y = -1; w = 7; h = 5; title = "Third Imperium"; break;
                    case "solomani": x = -2; y = 2; w = 5; h = 3; title = "Solomani Confederacy"; break;
                    case "zhodani": x = -8; y = -3; w = 5; h = 3; title = "Zhodani Consulate"; break;
                    case "hive":
                    case "hiver": x = 2; y = 1; w = 6; h = 4; title = "Hiver Federation"; break;
                    case "aslan": x = -8; y = 1; w = 7; h = 4; title = "Aslan Hierate"; break;
                    case "vargr": x = -4; y = -4; w = 8; h = 3; title = "Vargr Extents"; break;
                    // TODO: K'kree
                    // TODO: Zhodani provinces

                    case "jg": x = 160; y = 0; w = 2; h = 2; title = "Judges Guild"; break;

                    default:
                        SendError(context.Response, 404, "Not Found", String.Format("Unknown domain: {0}", domain));
                        return;
                }

                int x1 = x * Astrometrics.SectorWidth - Astrometrics.ReferenceHex.X + 1;
                int y1 = y * Astrometrics.SectorHeight - Astrometrics.ReferenceHex.Y + 1;
                int x2 = x1 + w * Astrometrics.SectorWidth - 1;
                int y2 = y1 + h * Astrometrics.SectorHeight - 1;

                tileRect.X = Math.Min(x1, x2);
                tileRect.Y = Math.Min(y1, y2);
                tileRect.Width = Math.Max(x1, x2) - tileRect.X;
                tileRect.Height = Math.Max(y1, y2) - tileRect.Y;

                SectorMap map = SectorMap.FromName(SectorMap.DefaultSetting, resourceManager);
                selector = new RectSelector(map, resourceManager, tileRect);
                selector.Slop = false;

                tileRect.Offset(-1, -1);
                tileRect.Width += 1;
                tileRect.Height += 1;

                // Account for jagged hexes
                tileRect.Height += 0.5f;
                tileRect.Inflate(0.25f, 0.10f);
                if (style == Stylesheet.Style.Candy)
                    tileRect.Width += 0.75f;

                clipOutsectorBorders = true;
            }
            else
            {
                // Sector - either POSTed or specified by name
                Sector sector = null;
                options = options & ~MapOptions.SectorGrid;

                if (context.Request.HttpMethod == "POST")
                {
                    try
                    {
                        bool lint = GetBoolOption(context, "lint", defaultValue: false);
                        ErrorLogger errors = new ErrorLogger();
                        sector = GetPostedSector(context.Request, errors);
                        if (lint && !errors.Empty)
                        {
                            SendError(context.Response, 400, "Bad Request", errors.ToString());
                        }
                    }
                    catch (Exception ex)
                    {
                        SendError(context.Response, 400, "Bad Request", ex.Message);
                        return;
                    }

                    if (sector == null)
                    {
                        SendError(context.Response, 400, "Bad Request", "Either file or data must be supplied in the POST data.");
                        return;
                    }

                    title = "User Data";

                    // TODO: Suppress all OTU rendering.
                    options = options & ~MapOptions.WorldsHomeworlds & ~MapOptions.WorldsCapitals;
                }
                else
                {
                    string sectorName = GetStringOption(context, "sector");
                    if (sectorName == null)
                    {
                        SendError(context.Response, 400, "Bad Request", "No sector specified.");
                        return;
                    }

                    SectorMap map = SectorMap.FromName(SectorMap.DefaultSetting, resourceManager);

                    sector = map.FromName(sectorName);
                    if (sector == null)
                    {
                        SendError(context.Response, 404, "Not Found", String.Format("The specified sector '{0}' was not found.", sectorName));
                        return;
                    }

                    title = sector.Names[0].Text;
                }

                if (sector != null && HasOption(context, "subsector") && GetStringOption(context, "subsector").Length > 0)
                {
                    options = options & ~MapOptions.SubsectorGrid;
                    string subsector = GetStringOption(context, "subsector");
                    int index = sector.SubsectorIndexFor(subsector);
                    if (index == -1)
                    {
                        SendError(context.Response, 404, "Not Found", String.Format("The specified subsector '{0}' was not found.", subsector));
                        return;
                    }

                    selector = new SubsectorSelector(resourceManager, sector, index);

                    tileRect = sector.SubsectorBounds(index);

                    options &= ~(MapOptions.SectorGrid | MapOptions.SubsectorGrid);

                    title = String.Format("{0} - Subsector {1}", title, 'A' + index);
                }
                else if (sector != null && HasOption(context, "quadrant") && GetStringOption(context, "quadrant").Length > 0)
                {
                    string quadrant = GetStringOption(context, "quadrant");
                    int index;
                    switch (quadrant.ToLowerInvariant()) {
                        case "alpha": index = 0; quadrant = "Alpha";  break;
                        case "beta": index = 1; quadrant = "Beta"; break;
                        case "gamma": index = 2; quadrant = "Gamma"; break;
                        case "delta": index = 3; quadrant = "Delta"; break;
                        default:
                            SendError(context.Response, 400, "Bad Request", String.Format("The specified quadrant '{0}' is invalid.", quadrant));
                            return;
                    }

                    selector = new QuadrantSelector(resourceManager, sector, index);
                    tileRect = sector.QuadrantBounds(index);

                    options &= ~(MapOptions.SectorGrid | MapOptions.SubsectorGrid | MapOptions.SectorsMask);

                    title = String.Format("{0} - {1} Quadrant", title, quadrant);
                }
                else
                {
                    selector = new SectorSelector(resourceManager, sector);
                    tileRect = sector.Bounds;

                    options &= ~(MapOptions.SectorGrid);
                }

                // Account for jagged hexes
                tileRect.Height += 0.5f;
                tileRect.Inflate(0.25f, 0.10f);
                if (style == Stylesheet.Style.Candy)
                    tileRect.Width += 0.75f;
                clipOutsectorBorders = false;
            }

            const double NormalScale = 64; // pixels/parsec - standard subsector-rendering scale
            double scale = Util.Clamp(GetDoubleOption(context, "scale", NormalScale), MinScale, MaxScale);

            int rot = GetIntOption(context, "rotation", 0) % 4;
            bool thumb = GetBoolOption(context, "thumb", false);

            Stylesheet stylesheet = new Stylesheet(scale, options, style);

            Size tileSize = new Size((int)Math.Floor(tileRect.Width * scale * Astrometrics.ParsecScaleX), (int)Math.Floor(tileRect.Height * scale * Astrometrics.ParsecScaleY));

            if (thumb)
            {
                tileSize.Width = (int)Math.Floor(16 * tileSize.Width / scale);
                tileSize.Height = (int)Math.Floor(16 * tileSize.Height / scale);
                scale = 16;
            }

            int bitmapWidth = tileSize.Width, bitmapHeight = tileSize.Height;
            float translateX = 0, translateY = 0, angle = rot * 90;
            switch (rot)
            {
                case 1: // 90 degrees clockwise
                    Util.Swap(ref bitmapWidth, ref bitmapHeight);
                    translateX = bitmapWidth;
                    break;
                case 2: // 180 degrees
                    translateX = bitmapWidth; translateY = bitmapHeight;
                    break;
                case 3: // 270 degrees clockwise
                    Util.Swap(ref bitmapWidth, ref bitmapHeight);
                    translateY = bitmapHeight;
                    break;
            }

            Render.RenderContext ctx = new Render.RenderContext();
            ctx.resourceManager = resourceManager;
            ctx.selector = selector;
            ctx.tileRect = tileRect;
            ctx.scale = scale;
            ctx.options = options;
            ctx.styles = stylesheet;
            ctx.tileSize = tileSize;
            ctx.clipOutsectorBorders = clipOutsectorBorders;
            ProduceResponse(context, title, ctx, new Size(bitmapWidth, bitmapHeight), rot, translateX, translateY);
        }
Beispiel #8
0
            public void ParseOptions(HttpRequest request, IDictionary<string, object> queryDefaults, ref MapOptions options, ref Stylesheet.Style style)
            {
                options = (MapOptions)GetIntOption("options", queryDefaults, (int)options);

#if LEGACY_STYLES
            // Handle deprecated/legacy options bits for selecting style
            style =
                (options & MapOptions.StyleMaskDeprecated) == MapOptions.PrintStyleDeprecated ? Stylesheet.Style.Atlas :
                (options & MapOptions.StyleMaskDeprecated) == MapOptions.CandyStyleDeprecated ? Stylesheet.Style.Candy :
                Stylesheet.Style.Poster;
#endif // LEGACY_STYLES

                if (HasOption("style", queryDefaults))
                {
                    string opt = GetStringOption("style", queryDefaults).ToLowerInvariant();
                    if (!s_nameToStyle.ContainsKey(opt))
                        throw new HttpError(400, "Bad Request", String.Format("Invalid style option: {0}", opt));
                    style = s_nameToStyle[opt];
                }
            }
Beispiel #9
0
 protected void ParseOptions(ref MapOptions options, ref Stylesheet.Style style)
 {
     ParseOptions(context.Request, Defaults(context), ref options, ref style);
 }
Beispiel #10
0
            public override void Process()
            {
                // NOTE: This (re)initializes a static data structure used for
                // resolving names into sector locations, so needs to be run
                // before any other objects (e.g. Worlds) are loaded.
                ResourceManager resourceManager = new ResourceManager(context.Server);

                //
                // Jump
                //
                int jump = Util.Clamp(GetIntOption("jump", 6), 0, 12);

                //
                // Content & Coordinates
                //
                Selector selector;
                Location loc;
                if (context.Request.HttpMethod == "POST")
                {
                    Sector sector;
                    bool lint = GetBoolOption("lint", defaultValue: false);
                    ErrorLogger errors = new ErrorLogger();
                    sector = GetPostedSector(context.Request, errors);
                    if (lint && !errors.Empty)
                        throw new HttpError(400, "Bad Request", errors.ToString());

                    if (sector == null)
                        throw new HttpError(400, "Bad Request", "Either file or data must be supplied in the POST data.");

                    int hex = GetIntOption("hex", Astrometrics.SectorCentralHex);
                    loc = new Location(new Point(0, 0), hex);
                    selector = new HexSectorSelector(resourceManager, sector, loc.Hex, jump);
                }
                else
                {
                    SectorMap.Milieu map = SectorMap.ForMilieu(resourceManager, GetStringOption("milieu"));

                    if (HasOption("sector") && HasOption("hex"))
                    {
                        string sectorName = GetStringOption("sector");
                        int hex = GetIntOption("hex", 0);
                        Sector sector = map.FromName(sectorName);
                        if (sector == null)
                            throw new HttpError(404, "Not Found", string.Format("The specified sector '{0}' was not found.", sectorName));

                        loc = new Location(sector.Location, hex);
                    }
                    else if (HasLocation())
                    {
                        loc = GetLocation();
                    }
                    else
                    {
                        loc = new Location(map.FromName("Spinward Marches").Location, 1910);
                    }
                    selector = new HexSelector(map, resourceManager, loc, jump);
                }

                //
                // Scale
                //
                double scale = Util.Clamp(GetDoubleOption("scale", 64), MinScale, MaxScale);

                //
                // Options & Style
                //
                MapOptions options = MapOptions.BordersMajor | MapOptions.BordersMinor | MapOptions.ForceHexes;
                Stylesheet.Style style = Stylesheet.Style.Poster;
                ParseOptions(ref options, ref style);

                //
                // Border
                //
                bool border = GetBoolOption("border", defaultValue: true);

                //
                // Clip
                //
                bool clip = GetBoolOption("clip", defaultValue: true);

                //
                // What to render
                //

                RectangleF tileRect = new RectangleF();

                Point coords = Astrometrics.LocationToCoordinates(loc);
                tileRect.X = coords.X - jump - 1;
                tileRect.Width = jump + 1 + jump;
                tileRect.Y = coords.Y - jump - 1;
                tileRect.Height = jump + 1 + jump;

                // Account for jagged hexes
                tileRect.Y += (coords.X % 2 == 0) ? 0 : 0.5f;
                tileRect.Inflate(0.35f, 0.15f);

                Size tileSize = new Size((int)Math.Floor(tileRect.Width * scale * Astrometrics.ParsecScaleX), (int)Math.Floor(tileRect.Height * scale * Astrometrics.ParsecScaleY));

                // Construct clipping path
                List<Point> clipPath = new List<Point>(jump * 6 + 1);
                Point cur = coords;
                for (int i = 0; i < jump; ++i)
                {
                    // Move J parsecs to the upper-left (start of border path logic)
                    cur = Astrometrics.HexNeighbor(cur, 1);
                }
                clipPath.Add(cur);
                for (int dir = 0; dir < 6; ++dir)
                {
                    for (int i = 0; i < jump; ++i)
                    {
                        cur = Astrometrics.HexNeighbor(cur, (dir + 3) % 6); // Clockwise from upper left
                        clipPath.Add(cur);
                    }
                }

                Stylesheet styles = new Stylesheet(scale, options, style);

                // If any names are showing, show them all
                if (styles.worldDetails.HasFlag(WorldDetails.KeyNames))
                    styles.worldDetails |= WorldDetails.AllNames;

                // Compute path
                float[] edgeX, edgeY;
                RenderUtil.HexEdges(styles.hexStyle == HexStyle.Square ? PathUtil.PathType.Square : PathUtil.PathType.Hex,
                    out edgeX, out edgeY);
                PointF[] boundingPathCoords;
                byte[] boundingPathTypes;
                PathUtil.ComputeBorderPath(clipPath, edgeX, edgeY, out boundingPathCoords, out boundingPathTypes);

                RenderContext ctx = new RenderContext(resourceManager, selector, tileRect, scale, options, styles, tileSize);
                ctx.DrawBorder = border;
                ctx.ClipOutsectorBorders = true;

                // TODO: Widen path to allow for single-pixel border
                ctx.ClipPath = clip ? new XGraphicsPath(boundingPathCoords, boundingPathTypes, XFillMode.Alternate) : null;
                ProduceResponse(context, "Jump Map", ctx, tileSize, transparent: clip);
            }
Beispiel #11
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;
        }
            private static void BitmapResponse(HttpResponse response, Stream outputStream, Stylesheet styles, Bitmap bitmap, string mimeType)
            {
                try
                {
                    // JPEG or PNG if not specified, based on style
                    mimeType = mimeType ?? styles.preferredMimeType;

                    response.ContentType = mimeType;

                    // Searching for a matching encoder
                    ImageCodecInfo encoder = null;
                    ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
                    for (int i = 0; i < encoders.Length; ++i)
                    {
                        if (encoders[i].MimeType == response.ContentType)
                        {
                            encoder = encoders[i];
                            break;
                        }
                    }

                    if (encoder != null)
                    {
                        EncoderParameters encoderParams;
                        if (mimeType == MediaTypeNames.Image.Jpeg)
                        {
                            encoderParams = new EncoderParameters(1);
                            encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)95);
                        }
                        else if (mimeType == Util.MediaTypeName_Image_Png)
                        {
                            encoderParams = new EncoderParameters(1);
                            encoderParams.Param[0] = new EncoderParameter(Encoder.ColorDepth, 8);
                        }
                        else
                        {
                            encoderParams = new EncoderParameters(0);
                        }

                        if (mimeType == Util.MediaTypeName_Image_Png)
                        {
                            // PNG encoder is picky about streams - need to do an indirection
                            // http://www.west-wind.com/WebLog/posts/8230.aspx
                            using (var ms = new MemoryStream())
                            {
                                bitmap.Save(ms, encoder, encoderParams);
                                ms.WriteTo(outputStream);
                            }
                        }
                        else
                        {
                            bitmap.Save(outputStream, encoder, encoderParams);
                        }

                        encoderParams.Dispose();
                    }
                    else
                    {
                        // Default to GIF if we can't find anything
                        response.ContentType = MediaTypeNames.Image.Gif;
                        bitmap.Save(outputStream, ImageFormat.Gif);
                    }
                }
                catch (System.Runtime.InteropServices.ExternalException)
                {
                    // Saving seems to throw "A generic error occurred in GDI+." on low memory.
                    throw new HttpError(500, "Internal Server Error",
                        String.Format("Unknown GDI error encoding bitmap ({0}x{1}). Insufficient memory?", bitmap.Width, bitmap.Height));
                }
            }