コード例 #1
0
            protected void ProduceResponse(HttpContext context, ITypeAccepter accepter, string title, RenderContext ctx, Size tileSize,
                                           AbstractMatrix transform,
                                           bool transparent = false, IDictionary <string, object> queryDefaults = null)
            {
                // New-style Options

                #region URL Parameters
                // TODO: move to ParseOptions (maybe - requires options to be parsed after stylesheet creation?)
                if (GetBoolOption("sscoords", queryDefaults: queryDefaults, defaultValue: false))
                {
                    ctx.Styles.hexCoordinateStyle = HexCoordinateStyle.Subsector;
                }

                if (GetBoolOption("allhexes", queryDefaults: queryDefaults, defaultValue: false))
                {
                    ctx.Styles.numberAllHexes = true;
                }

                if (GetBoolOption("nogrid", queryDefaults: queryDefaults, defaultValue: false))
                {
                    ctx.Styles.parsecGrid.visible = false;
                }

                if (!GetBoolOption("routes", queryDefaults: queryDefaults, defaultValue: true))
                {
                    ctx.Styles.macroRoutes.visible = false;
                    ctx.Styles.microRoutes.visible = false;
                }

                if (!GetBoolOption("rifts", queryDefaults: queryDefaults, defaultValue: true))
                {
                    ctx.Styles.showRiftOverlay = false;
                }

                if (GetBoolOption("po", queryDefaults: queryDefaults, defaultValue: false))
                {
                    ctx.Styles.populationOverlay.visible = true;
                }

                if (GetBoolOption("im", queryDefaults: queryDefaults, defaultValue: false))
                {
                    ctx.Styles.importanceOverlay.visible = true;
                }

                if (GetBoolOption("cp", queryDefaults: queryDefaults, defaultValue: false))
                {
                    ctx.Styles.capitalOverlay.visible = true;
                }

                if (GetBoolOption("stellar", queryDefaults: queryDefaults, defaultValue: false))
                {
                    ctx.Styles.showStellarOverlay = true;
                }

                ctx.Styles.dimUnofficialSectors    = GetBoolOption("dimunofficial", queryDefaults: queryDefaults, defaultValue: false);
                ctx.Styles.colorCodeSectorStatus   = GetBoolOption("review", queryDefaults: queryDefaults, defaultValue: false);
                ctx.Styles.droyneWorlds.visible    = GetBoolOption("dw", queryDefaults: queryDefaults, defaultValue: false);
                ctx.Styles.minorHomeWorlds.visible = GetBoolOption("mh", queryDefaults: queryDefaults, defaultValue: false);
                ctx.Styles.ancientsWorlds.visible  = GetBoolOption("an", queryDefaults: queryDefaults, defaultValue: false);

                // TODO: Return an error if pattern is invalid?
                ctx.Styles.highlightWorldsPattern = HighlightWorldPattern.Parse(
                    GetStringOption("hw", queryDefaults: queryDefaults, defaultValue: String.Empty).Replace(' ', '+'));
                ctx.Styles.highlightWorlds.visible = ctx.Styles.highlightWorldsPattern != null;

                double devicePixelRatio = GetDoubleOption("dpr", defaultValue: 1, queryDefaults: queryDefaults);
                devicePixelRatio = Math.Round(devicePixelRatio, 1);
                if (devicePixelRatio <= 0)
                {
                    devicePixelRatio = 1;
                }
                if (devicePixelRatio > 2)
                {
                    devicePixelRatio = 2;
                }

                bool dataURI = GetBoolOption("datauri", queryDefaults: queryDefaults, defaultValue: false);

                if (GetStringOption("milieu", SectorMap.DEFAULT_MILIEU) != SectorMap.DEFAULT_MILIEU)
                {
                    // TODO: Make this declarative in resource files.
                    if (ctx.Styles.macroBorders.visible)
                    {
                        ctx.Styles.macroBorders.visible = false;
                        ctx.Styles.microBorders.visible = true;
                    }
                    ctx.Styles.macroNames.visible  = false;
                    ctx.Styles.macroRoutes.visible = false;
                }
                #endregion

                MemoryStream ms = null;
                if (dataURI)
                {
                    ms = new MemoryStream();
                }
                Stream outputStream = ms ?? Context.Response.OutputStream;

                if (accepter.Accepts(context, ContentTypes.Image.Svg, ignoreHeaderFallbacks: true))
                {
                    #region SVG Generation
                    using (var svg = new SVGGraphics(tileSize.Width, tileSize.Height))
                    {
                        RenderToGraphics(ctx, transform, svg);

                        using (var stream = new MemoryStream())
                        {
                            svg.Serialize(new StreamWriter(stream));
                            context.Response.ContentType = ContentTypes.Image.Svg;
                            if (!dataURI)
                            {
                                context.Response.AddHeader("content-length", stream.Length.ToString());
                                context.Response.AddHeader("content-disposition", $"inline;filename=\"{Util.SanitizeFilename(title)}.svg\"");
                            }
                            stream.WriteTo(outputStream);
                        }
                    }
                    #endregion
                }

                else if (accepter.Accepts(context, ContentTypes.Application.Pdf, ignoreHeaderFallbacks: true))
                {
                    #region PDF Generation
                    using (var document = new PdfDocument())
                    {
                        document.Version       = 14; // 1.4 for opacity
                        document.Info.Title    = title;
                        document.Info.Author   = "Joshua Bell";
                        document.Info.Creator  = "TravellerMap.com";
                        document.Info.Subject  = DateTime.Now.ToString("F", CultureInfo.InvariantCulture);
                        document.Info.Keywords = "The Traveller game in all forms is owned by Far Future Enterprises. Copyright (C) 1977 - 2019 Far Future Enterprises. Traveller is a registered trademark of Far Future Enterprises.";

                        // TODO: Credits/Copyright
                        // This is close, but doesn't define the namespace correctly:
                        // document.Info.Elements.Add( new KeyValuePair<string, PdfItem>( "/photoshop/Copyright", new PdfString( "HelloWorld" ) ) );

                        PdfPage page = document.AddPage();

                        // NOTE: only PageUnit currently supported in MGraphics is Points
                        page.Width  = XUnit.FromPoint(tileSize.Width);
                        page.Height = XUnit.FromPoint(tileSize.Height);

                        using (var gfx = new PdfSharpGraphics(XGraphics.FromPdfPage(page)))
                        {
                            RenderToGraphics(ctx, transform, gfx);

                            using (var stream = new MemoryStream())
                            {
                                document.Save(stream, closeStream: false);
                                context.Response.ContentType = ContentTypes.Application.Pdf;
                                if (!dataURI)
                                {
                                    context.Response.AddHeader("content-length", stream.Length.ToString());
                                    context.Response.AddHeader("content-disposition", $"inline;filename=\"{Util.SanitizeFilename(title)}.pdf\"");
                                }
                                stream.WriteTo(outputStream);
                            }
                        }
                    }
                    #endregion
                }
                else
                {
                    #region Bitmap Generation
                    int width  = (int)Math.Floor(tileSize.Width * devicePixelRatio);
                    int height = (int)Math.Floor(tileSize.Height * devicePixelRatio);
                    using (var bitmap = TryConstructBitmap(width, height, PixelFormat.Format32bppArgb))
                    {
                        if (bitmap == null)
                        {
                            throw new HttpError(500, "Internal Server Error",
                                                $"Failed to allocate bitmap ({width}x{height}). Insufficient memory?");
                        }

                        if (transparent)
                        {
                            bitmap.MakeTransparent();
                        }

                        using (var g = System.Drawing.Graphics.FromImage(bitmap))
                        {
                            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

                            using (var graphics = new BitmapGraphics(g))
                            {
                                graphics.ScaleTransform((float)devicePixelRatio);
                                RenderToGraphics(ctx, transform, graphics);
                            }
                        }

                        BitmapResponse(context.Response, outputStream, ctx.Styles, bitmap, transparent ? ContentTypes.Image.Png : null);
                    }
                    #endregion
                }

                if (dataURI)
                {
                    string contentType = context.Response.ContentType;
                    context.Response.ContentType = ContentTypes.Text.Plain;
                    ms.Seek(0, SeekOrigin.Begin);

                    context.Response.Output.Write("data:");
                    context.Response.Output.Write(contentType);
                    context.Response.Output.Write(";base64,");
                    context.Response.Output.Flush();

                    System.Security.Cryptography.ICryptoTransform encoder = new System.Security.Cryptography.ToBase64Transform();
                    using (System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(context.Response.OutputStream, encoder, System.Security.Cryptography.CryptoStreamMode.Write))
                    {
                        ms.WriteTo(cs);
                        cs.FlushFinalBlock();
                    }
                }

                context.Response.Flush();
                context.Response.Close();
                return;
            }