예제 #1
0
        public Stylesheet(double scale, MapOptions options, Style style)
        {
            float onePixel = 1f / (float)scale;

            grayscale       = false;
            lightBackground = false;

            subsectorGrid.visible  = ((scale >= SubsectorsMinScale) && options.HasFlag(MapOptions.SubsectorGrid));
            sectorGrid.visible     = ((scale >= SectorGridMinScale) && options.HasFlag(MapOptions.SectorGrid));
            parsecGrid.visible     = (scale >= ParsecMinScale);
            showSomeSectorNames    = ((scale >= SectorNameMinScale) && (scale <= SectorNameMaxScale) && ((options & MapOptions.SectorsMask) != 0));
            showAllSectorNames     = showSomeSectorNames && ((scale >= SectorNameAllSelectedScale) || options.HasFlag(MapOptions.SectorsAll));
            subsectorNames.visible = ((scale >= SubsectorNameMinScale) && (scale <= SubsectorNameMaxScale) && ((options & MapOptions.SectorsMask) != 0));

            worlds.visible            = (scale >= WorldMinScale);
            pseudoRandomStars.visible = (PseudoRandomStarsMinScale <= scale) && (scale <= PseudoRandomStarsMaxScale);
            showRiftOverlay           = (scale <= PseudoRandomStarsMaxScale || style == Style.Candy);

            t5AllegianceCodes = scale >= T5AllegianceCodeMinScale;

            riftOpacity = ScaleInterpolate(0f, 0.85f, scale, 1 / 4f, 4f);

            deepBackgroundOpacity = ScaleInterpolate(1f, 0f, scale, 1 / 8f, 2f);

            macroRoutes.visible = (scale >= MacroRouteMinScale) && (scale <= MacroRouteMaxScale);
            macroNames.visible  = (scale >= MacroLabelMinScale) && (scale <= MacroLabelMaxScale);
            megaNames.visible   = scale <= MegaLabelMaxScale && ((options & MapOptions.NamesMask) != 0);
            showMicroNames      = ((scale >= MicroNameMinScale) && ((options & MapOptions.NamesMask) != 0));
            capitals.visible    = (scale >= MacroWorldsMinScale) && (scale <= MacroWorldsMaxScale);

            hexStyle = (((options & MapOptions.ForceHexes) == 0) && (scale < ParsecHexMinScale))
                ? HexStyle.Square
                : HexStyle.Hex;
            microBorderStyle = hexStyle == HexStyle.Square ? MicroBorderStyle.Square : MicroBorderStyle.Hex;

            macroBorders.visible = (scale >= MacroBorderMinScale) && (scale < MicroBorderMinScale) && ((options & MapOptions.BordersMask) != 0);
            microBorders.visible = (scale >= MicroBorderMinScale) && ((options & MapOptions.BordersMask) != 0);
            fillMicroBorders     = microBorders.visible && options.HasFlag(MapOptions.FilledBorders);
            microRoutes.visible  = (scale >= RouteMinScale);

            worldDetails = !worlds.visible ? WorldDetails.None :
                           (scale < WorldBasicMinScale) ? WorldDetails.Dotmap :
                           (scale < WorldFullMinScale) ? WorldDetails.Atlas :
                           WorldDetails.Poster;

            showWorldDetailColors = worldDetails == WorldDetails.Poster && options.HasFlag(MapOptions.WorldColors);

            lowerCaseAllegiance = (scale < WorldFullMinScale);

            worlds.textBackgroundStyle = TextBackgroundStyle.Rectangle;

            hexCoordinateStyle = HexCoordinateStyle.Sector;
            numberAllHexes     = false;

            if (scale < WorldFullMinScale)
            {
                // Atlas-style

                const float x = 0.225f;
                const float y = 0.125f;

                BaseTopPosition.X    = -x;
                BaseTopPosition.Y    = -y;
                BaseBottomPosition.X = -x;
                BaseBottomPosition.Y = y;
                GasGiantPosition.X   = x;
                GasGiantPosition.Y   = -y;
                AllegiancePosition.X = x;
                AllegiancePosition.Y = y;

                BaseMiddlePosition.X = options.HasFlag(MapOptions.ForceHexes) ? -0.35f : -0.2f;
                BaseMiddlePosition.Y = 0;
                StarportPosition.X   = 0.0f;
                StarportPosition.Y   = -0.24f;
                worlds.position.X    = 0.0f;
                worlds.position.Y    = 0.4f;
            }
            else
            {
                // Poster-style

                const float x = 0.25f;
                const float y = 0.18f;

                BaseTopPosition.X    = -x;
                BaseTopPosition.Y    = -y;
                BaseBottomPosition.X = -x;
                BaseBottomPosition.Y = y;
                GasGiantPosition.X   = x;
                GasGiantPosition.Y   = -y;
                AllegiancePosition.X = x;
                AllegiancePosition.Y = y;

                BaseMiddlePosition.X = -0.35f;
                BaseMiddlePosition.Y = 0f;
                StarportPosition.X   = 0f;
                StarportPosition.Y   = -0.225f;
                worlds.position.X    = 0.0f;
                worlds.position.Y    = 0.37f; // Don't hide hex bottom, leave room for UWP
            }

            if (scale >= WorldUwpMinScale)
            {
                worldDetails        |= WorldDetails.Uwp;
                BaseBottomPosition.Y = 0.1f;
                BaseMiddlePosition.Y = (BaseBottomPosition.Y + BaseTopPosition.Y) / 2;
                AllegiancePosition.Y = 0.1f;
            }

            if (worlds.visible)
            {
                float fontScale = (scale <= 96f || style == Style.Candy) ? 1f : 96f / Math.Min((float)scale, 192f);

                worlds.fontInfo      = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.2f : 0.15f * fontScale, FontStyle.Bold);
                wingdingFont         = new FontInfo("Wingdings", scale < WorldFullMinScale ? 0.2f : 0.175f * fontScale);
                glyphFont            = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.175f : 0.15f * fontScale, FontStyle.Bold);
                hexNumber.fontInfo   = new FontInfo(DEFAULT_FONT, 0.1f * fontScale);
                worlds.smallFontInfo = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.2f : 0.1f * fontScale, FontStyle.Regular);
                worlds.largeFontInfo = worlds.fontInfo;
                starportFont         = (scale < WorldFullMinScale) ? worlds.smallFontInfo : worlds.fontInfo;
            }

            sectorName.fontInfo     = new FontInfo(DEFAULT_FONT, 5.5f);
            subsectorNames.fontInfo = new FontInfo(DEFAULT_FONT, 1.5f);

            float overlayFontSize = Math.Max(onePixel * 12f, 0.375f);

            droyneWorlds.fontInfo    = new FontInfo(DEFAULT_FONT, overlayFontSize);
            ancientsWorlds.fontInfo  = new FontInfo(DEFAULT_FONT, overlayFontSize);
            minorHomeWorlds.fontInfo = new FontInfo(DEFAULT_FONT, overlayFontSize);

            droyneWorlds.content    = "\u2605\u2606"; // BLACK STAR / WHITE STAR
            minorHomeWorlds.content = "\u273B";       // TEARDROP-SPOKED ASTERISK
            ancientsWorlds.content  = "\u2600";       // BLACK SUN WITH RAYS

            microBorders.fontInfo      = new FontInfo(DEFAULT_FONT, (scale == MicroNameMinScale) ? 0.6f : 0.25f, FontStyle.Bold);
            microBorders.smallFontInfo = new FontInfo(DEFAULT_FONT, 0.15f, FontStyle.Bold);
            microBorders.largeFontInfo = new FontInfo(DEFAULT_FONT, 0.75f, FontStyle.Bold);

            macroNames.fontInfo       = new FontInfo(DEFAULT_FONT, 8f / 1.4f, FontStyle.Bold);
            macroNames.smallFontInfo  = new FontInfo(DEFAULT_FONT, 5f / 1.4f, FontStyle.Regular);
            macroNames.mediumFontInfo = new FontInfo(DEFAULT_FONT, 6.5f / 1.4f, FontStyle.Italic);

            float megaNameScaleFactor = Math.Min(35f, 0.75f * onePixel);

            megaNames.fontInfo       = new FontInfo(DEFAULT_FONT, 24f * megaNameScaleFactor, FontStyle.Bold);
            megaNames.mediumFontInfo = new FontInfo(DEFAULT_FONT, 22f * megaNameScaleFactor, FontStyle.Regular);
            megaNames.smallFontInfo  = new FontInfo(DEFAULT_FONT, 18f * megaNameScaleFactor, FontStyle.Italic);

            capitals.fillColor     = Color.Wheat;
            capitals.textColor     = Color.Red;
            blueZone.pen.color     = Color.Blue;
            amberZone.pen.color    = Color.Gold;
            redZone.pen.color      = Color.Red;
            macroBorders.pen.color = Color.Red;
            macroRoutes.pen.color  = Color.White;
            microBorders.pen.color = Color.Gray;
            Color gridColor = Color.FromArgb(ScaleInterpolate(0, 255, scale, SectorGridMinScale, SectorGridFullScale), Color.Gray);

            microRoutes.pen.color = Color.Gray;

            Color foregroundColor = Color.White;

            backgroundColor = Color.Black;
            Color lightColor     = Color.LightGray;
            Color darkColor      = Color.DarkGray;
            Color dimColor       = Color.DimGray;
            Color highlightColor = Color.Red;

            microBorders.textColor = Color.Gold;
            worldWater.fillColor   = Color.DeepSkyBlue;
            worldNoWater.fillColor = Color.White;
            worldNoWater.pen.color = Color.Empty;

            parsecGrid.pen    = new PenInfo(gridColor, onePixel);
            subsectorGrid.pen = new PenInfo(gridColor, onePixel * 2);
            sectorGrid.pen    = new PenInfo(gridColor, (subsectorGrid.visible ? 4 : 2) * onePixel);
            worldWater.pen    = new PenInfo(Color.Empty, Math.Max(0.01f, onePixel));

            microBorders.textStyle.Rotation    = 0;
            microBorders.textStyle.Translation = new PointF(0, 0);
            microBorders.textStyle.Scale       = new SizeF(1.0f, 1.0f);
            microBorders.textStyle.Uppercase   = false;

            sectorName.textStyle.Rotation    = -50; // degrees
            sectorName.textStyle.Translation = new PointF(0, 0);
            sectorName.textStyle.Scale       = new SizeF(0.75f, 1.0f);
            sectorName.textStyle.Uppercase   = false;
            sectorName.textStyle.Wrap        = true;

            subsectorNames.textStyle = sectorName.textStyle;

            worlds.textStyle.Rotation    = 0;
            worlds.textStyle.Scale       = new SizeF(1.0f, 1.0f);
            worlds.textStyle.Translation = worlds.position;
            worlds.textStyle.Uppercase   = false;

            showNebulaBackground = false;
            showGalaxyBackground = deepBackgroundOpacity > 0.0f;
            useWorldImages       = false;

            // Cap pen widths when zooming in
            float penScale = (scale <= 64) ? 1f : (64f / (float)scale);

            float borderPenWidth =
                (scale < MicroBorderMinScale) ? 1 : // When rendering vector borders
                (scale < ParsecMinScale) ? 1 :      // When not rendering "hexes"
                0.16f * penScale;                   // ... but cut in half by clipping

            float routePenWidth =
                scale <= 16 ? 0.2f :
                0.08f * penScale;

            microBorders.pen.width = borderPenWidth;
            macroBorders.pen.width = borderPenWidth;
            microRoutes.pen.width  = routePenWidth;

            amberZone.pen.width = redZone.pen.width = blueZone.pen.width = 0.05f * penScale;

            macroRoutes.pen.width     = borderPenWidth;
            macroRoutes.pen.dashStyle = DashStyle.Dash;

            populationOverlay.fillColor = Color.FromArgb(0x80, 0xff, 0xff, 0x00);
            importanceOverlay.fillColor = Color.FromArgb(0x20, 0x80, 0xff, 0x00);
            highlightWorlds.fillColor   = Color.FromArgb(0x80, 0xff, 0x00, 0x00);

            populationOverlay.pen = new PenInfo(Color.Empty, 0.03f * penScale, DashStyle.Dash);
            importanceOverlay.pen = new PenInfo(Color.Empty, 0.03f * penScale, DashStyle.Dot);
            highlightWorlds.pen   = new PenInfo(Color.Empty, 0.03f * penScale, DashStyle.DashDot);

            switch (style)
            {
            case Style.Poster:
            {
                // This is the default - no changes
                break;
            }

            case Style.Atlas:
            {
                grayscale       = true;
                lightBackground = true;

                capitals.fillColor     = Color.DarkGray;
                capitals.textColor     = Color.Black;
                amberZone.pen.color    = Color.LightGray;
                blueZone.pen.color     = Color.Gray;     // TODO: make dashed
                redZone.pen.color      = Color.Black;
                macroBorders.pen.color = Color.Black;
                macroRoutes.pen.color  = Color.Gray;
                microBorders.pen.color = Color.Black;
                microRoutes.pen.color  = Color.Gray;

                foregroundColor        = Color.Black;
                backgroundColor        = Color.White;
                lightColor             = Color.DarkGray;
                darkColor              = Color.DarkGray;
                dimColor               = Color.LightGray;
                highlightColor         = Color.Gray;
                microBorders.textColor = Color.Gray;
                worldWater.fillColor   = Color.Black;
                worldNoWater.fillColor = Color.Empty;

                worldNoWater.fillColor = Color.White;
                worldNoWater.pen       = new PenInfo(Color.Black, onePixel);

                riftOpacity = Math.Min(riftOpacity, 0.70f);

                showWorldDetailColors = false;

                populationOverlay.fillColor = Color.FromArgb(0x40, highlightColor);
                populationOverlay.pen.color = Color.Gray;

                importanceOverlay.fillColor = Color.FromArgb(0x20, highlightColor);
                importanceOverlay.pen.color = Color.Gray;

                highlightWorlds.fillColor = Color.FromArgb(0x30, highlightColor);
                highlightWorlds.pen.color = Color.Gray;

                break;
            }

            case Style.FASA:
            {
                showGalaxyBackground  = false;
                deepBackgroundOpacity = 0f;
                riftOpacity           = 0;

                Color inkColor = Color.FromArgb(0x5C, 0x40, 0x33);

                foregroundColor = inkColor;
                backgroundColor = Color.White;

                grayscale       = true;   // TODO: Tweak to be "monochrome"
                lightBackground = true;

                capitals.fillColor  = inkColor;
                capitals.textColor  = inkColor;
                amberZone.pen.color = inkColor;
                amberZone.pen.width = onePixel * 2;
                blueZone.pen.color  = inkColor;        // TODO: make dashed
                redZone.pen.color   = Color.Empty;
                redZone.fillColor   = Color.FromArgb(0x80, inkColor);

                macroBorders.pen.color = inkColor;
                macroRoutes.pen.color  = inkColor;

                microBorders.pen.color      = inkColor;
                microBorders.pen.width      = onePixel * 2;
                microBorders.fontInfo.size *= 0.6f;
                microBorders.fontInfo.style = FontStyle.Regular;

                microRoutes.pen.color = inkColor;

                lightColor             = Color.FromArgb(0x80, inkColor);
                darkColor              = inkColor;
                dimColor               = inkColor;
                highlightColor         = inkColor;
                microBorders.textColor = inkColor;
                hexStyle               = HexStyle.Hex;
                microBorderStyle       = MicroBorderStyle.Curve;

                parsecGrid.pen.color    = lightColor;
                sectorGrid.pen.color    = lightColor;
                subsectorGrid.pen.color = lightColor;

                worldWater.fillColor   = inkColor;
                worldNoWater.fillColor = inkColor;
                worldWater.pen.color   = Color.Empty;
                worldNoWater.pen.color = Color.Empty;

                showWorldDetailColors = false;

                worldDetails                 = worldDetails & ~WorldDetails.Starport;
                worldDetails                 = worldDetails & ~WorldDetails.Allegiance;
                worldDetails                 = worldDetails & ~WorldDetails.Bases;
                worldDetails                 = worldDetails & ~WorldDetails.GasGiant;
                worldDetails                 = worldDetails & ~WorldDetails.Highlight;
                worldDetails                 = worldDetails & ~WorldDetails.Uwp;
                worlds.fontInfo.size        *= 0.85f;
                worlds.textStyle.Translation = new PointF(0, 0.25f);

                numberAllHexes     = true;
                hexCoordinateStyle = HexCoordinateStyle.Subsector;
                overrideLineStyle  = LineStyle.Solid;

                populationOverlay.fillColor = Color.FromArgb(0x40, highlightColor);
                populationOverlay.pen.color = Color.Gray;

                importanceOverlay.fillColor = Color.FromArgb(0x20, highlightColor);
                importanceOverlay.pen.color = Color.Gray;

                highlightWorlds.fillColor = Color.FromArgb(0x30, highlightColor);
                highlightWorlds.pen.color = Color.Gray;

                break;
            }

            case Style.Print:
            {
                lightBackground = true;

                foregroundColor       = Color.Black;
                backgroundColor       = Color.White;
                lightColor            = Color.DarkGray;
                darkColor             = Color.DarkGray;
                dimColor              = Color.LightGray;
                microRoutes.pen.color = Color.Gray;

                microBorders.textColor = Color.Brown;

                amberZone.pen.color    = Color.Gold;
                worldNoWater.fillColor = Color.White;
                worldNoWater.pen       = new PenInfo(Color.Black, onePixel);

                riftOpacity = Math.Min(riftOpacity, 0.70f);

                populationOverlay.fillColor = Color.FromArgb(0x40, populationOverlay.fillColor);
                populationOverlay.pen.color = Color.Gray;

                importanceOverlay.fillColor = Color.FromArgb(0x20, importanceOverlay.fillColor);
                importanceOverlay.pen.color = Color.Gray;

                highlightWorlds.fillColor = Color.FromArgb(0x30, highlightWorlds.fillColor);
                highlightWorlds.pen.color = Color.Gray;

                break;
            }

            case Style.Draft:
            {
                int inkOpacity = 0xB0;

                showGalaxyBackground = false;
                lightBackground      = true;

                deepBackgroundOpacity = 0f;

                backgroundColor = Color.AntiqueWhite;
                foregroundColor = Color.FromArgb(inkOpacity, Color.Black);
                highlightColor  = Color.FromArgb(inkOpacity, Color.Red);

                lightColor = Color.FromArgb(inkOpacity, Color.DarkCyan);
                darkColor  = Color.FromArgb(inkOpacity, Color.Black);
                dimColor   = Color.FromArgb(inkOpacity / 2, Color.Black);


                subsectorGrid.pen.color = Color.FromArgb(inkOpacity, Color.Firebrick);

                const string FONT_NAME = "Comic Sans MS";
                worlds.fontInfo.name      = FONT_NAME;
                worlds.smallFontInfo.name = FONT_NAME;
                starportFont.name         = FONT_NAME;
                worlds.largeFontInfo.name = FONT_NAME;
                worlds.largeFontInfo.size = worlds.fontInfo.size * 1.25f;
                worlds.fontInfo.size     *= 0.8f;

                macroNames.fontInfo.name        = FONT_NAME;
                macroNames.mediumFontInfo.name  = FONT_NAME;
                macroNames.smallFontInfo.name   = FONT_NAME;
                megaNames.fontInfo.name         = FONT_NAME;
                megaNames.mediumFontInfo.name   = FONT_NAME;
                megaNames.smallFontInfo.name    = FONT_NAME;
                microBorders.smallFontInfo.name = FONT_NAME;
                microBorders.largeFontInfo.name = FONT_NAME;
                microBorders.fontInfo.name      = FONT_NAME;
                macroBorders.fontInfo.name      = FONT_NAME;
                macroRoutes.fontInfo.name       = FONT_NAME;
                capitals.fontInfo.name          = FONT_NAME;
                macroBorders.smallFontInfo.name = FONT_NAME;

                microBorders.textStyle.Uppercase = true;

                sectorName.textStyle.Uppercase     = true;
                subsectorNames.textStyle.Uppercase = true;

                // TODO: Render small, around edges
                subsectorNames.visible = false;

                worlds.textStyle.Uppercase = true;

                // TODO: Decide on this. It's nice to not overwrite the parsec grid, but
                // it looks very cluttered, especially amber/red zones.
                worlds.textBackgroundStyle = TextBackgroundStyle.None;

                worldDetails = worldDetails & ~WorldDetails.Allegiance;

                subsectorNames.fontInfo.name = FONT_NAME;
                sectorName.fontInfo.name     = FONT_NAME;

                worlds.largeFontInfo.style |= FontStyle.Underline;

                microBorders.pen.width     = onePixel * 4;
                microBorders.pen.dashStyle = DashStyle.Dot;

                worldNoWater.fillColor = foregroundColor;
                worldWater.fillColor   = Color.Empty;
                worldWater.pen         = new PenInfo(foregroundColor, onePixel * 2);

                amberZone.pen.color = foregroundColor;
                amberZone.pen.width = onePixel;
                redZone.pen.width   = onePixel * 2;

                microRoutes.pen.color = Color.Gray;

                parsecGrid.pen.color   = lightColor;
                microBorders.textColor = Color.FromArgb(inkOpacity, Color.Brown);

                riftOpacity = Math.Min(riftOpacity, 0.30f);

                numberAllHexes = true;

                populationOverlay.fillColor = Color.FromArgb(0x40, populationOverlay.fillColor);
                populationOverlay.pen.color = Color.Gray;

                importanceOverlay.fillColor = Color.FromArgb(0x20, importanceOverlay.fillColor);
                importanceOverlay.pen.color = Color.Gray;

                highlightWorlds.fillColor = Color.FromArgb(0x30, highlightWorlds.fillColor);
                highlightWorlds.pen.color = Color.Gray;

                break;
            }

            case Style.Candy:
            {
                useWorldImages            = true;
                pseudoRandomStars.visible = false;

                showNebulaBackground = deepBackgroundOpacity < 0.5f;

                hexStyle         = HexStyle.None;
                microBorderStyle = MicroBorderStyle.Curve;

                sectorGrid.visible    = sectorGrid.visible && (scale >= 4);
                subsectorGrid.visible = subsectorGrid.visible && (scale >= 32);
                parsecGrid.visible    = false;

                subsectorGrid.pen.width       = 0.03f * (64.0f / (float)scale);
                subsectorGrid.pen.dashStyle   = DashStyle.Custom;
                subsectorGrid.pen.dashPattern = new float[] { 10.0f, 8.0f };

                sectorGrid.pen.width       = 0.03f * (64.0f / (float)scale);
                sectorGrid.pen.dashStyle   = DashStyle.Custom;
                sectorGrid.pen.dashPattern = new float[] { 10.0f, 8.0f };

                worlds.textBackgroundStyle = TextBackgroundStyle.Shadow;

                worldDetails = worldDetails
                               & ~WorldDetails.Starport & ~WorldDetails.Allegiance & ~WorldDetails.Bases & ~WorldDetails.Hex;

                if (scale < CandyMinWorldNameScale)
                {
                    worldDetails = worldDetails & ~WorldDetails.KeyNames & ~WorldDetails.AllNames;
                }
                if (scale < CandyMinUwpScale)
                {
                    worldDetails = worldDetails & ~WorldDetails.Uwp;
                }

                amberZone.pen.color = Color.Goldenrod;

                sectorName.textStyle.Rotation    = 0;
                sectorName.textStyle.Translation = new PointF(0, -0.25f);
                sectorName.textStyle.Scale       = new SizeF(0.5f, 0.25f);
                sectorName.textStyle.Uppercase   = true;

                subsectorNames.textStyle.Rotation    = 0;
                subsectorNames.textStyle.Translation = new PointF(0, -0.25f);
                subsectorNames.textStyle.Scale       = new SizeF(0.3f, 0.15f);   // Expand
                subsectorNames.textStyle.Uppercase   = true;

                microBorders.textStyle.Rotation    = 0;
                microBorders.textStyle.Translation = new PointF(0, 0.25f);
                microBorders.textStyle.Scale       = new SizeF(1.0f, 0.5f);   // Expand
                microBorders.textStyle.Uppercase   = true;

                microBorders.pen.color = Color.FromArgb(128, Color.Red);

                worlds.textStyle.Rotation    = 0;
                worlds.textStyle.Scale       = new SizeF(1f, 0.5f);   // Expand
                worlds.textStyle.Translation = new PointF(0, 0);
                worlds.textStyle.Uppercase   = true;

                if (scale > CandyMaxWorldRelativeScale)
                {
                    hexContentScale = CandyMaxWorldRelativeScale / (float)scale;
                }

                break;
            }
            }

            sectorName.textColor = scale < 16 ? foregroundColor :
                                   scale < 48 ? darkColor : dimColor;
            subsectorNames.textColor = scale < 16 ? foregroundColor :
                                       scale < 48 ? darkColor : dimColor;

            if (style == Style.Candy)
            {
                subsectorNames.textColor = sectorName.textColor = Color.FromArgb(128, Color.Goldenrod);

                amberZone.pen.width = redZone.pen.width = blueZone.pen.width = 0.035f;

                microRoutes.pen.width  = scale < CandyMaxRouteRelativeScale ? routePenWidth : routePenWidth / 2;
                macroBorders.pen.width = scale < CandyMaxBorderRelativeScale ? borderPenWidth : borderPenWidth / 4;
                microBorders.pen.width = scale < CandyMaxBorderRelativeScale ? borderPenWidth : borderPenWidth / 4;
            }

            preferredMimeType = (style == Style.Candy)
                ? System.Net.Mime.MediaTypeNames.Image.Jpeg
                : Util.MediaTypeName_Image_Png;

            pseudoRandomStars.fillColor = foregroundColor;
            droyneWorlds.textColor      = minorHomeWorlds.textColor = ancientsWorlds.textColor =
                microBorders.textColor;

            megaNames.textColor          = foregroundColor;
            megaNames.textHighlightColor = highlightColor;

            macroNames.textColor          = foregroundColor;
            macroNames.textHighlightColor = highlightColor;

            macroRoutes.textColor          = foregroundColor;
            macroRoutes.textHighlightColor = highlightColor;

            worlds.textColor          = foregroundColor;
            worlds.textHighlightColor = highlightColor;

            hexNumber.textColor = lightColor;
            imageBorderColor    = lightColor;

            placeholder.content   = "*";
            placeholder.fontInfo  = new FontInfo("Georgia", 0.6f);
            placeholder.textColor = foregroundColor;
            placeholder.position  = new PointF(0, 0.17f);
        }
예제 #2
0
        private const float WorldUwpMinScale = 96; // Above this: UWP shown above name

        #endregion Fields

        #region Constructors

        public Stylesheet(double scale, MapOptions options, Style style)
        {
            float onePixel = 1f / (float)scale;

            grayscale = false;
            lightBackground = false;

            subsectorGrid.visible = ((scale >= SubsectorsMinScale) && options.HasFlag(MapOptions.SubsectorGrid));
            sectorGrid.visible = ((scale >= SectorGridMinScale) && options.HasFlag(MapOptions.SectorGrid));
            parsecGrid.visible = (scale >= ParsecMinScale);
            showSomeSectorNames = ((scale >= SectorNameMinScale) && (scale <= SectorNameMaxScale) && ((options & MapOptions.SectorsMask) != 0));
            showAllSectorNames = showSomeSectorNames && ((scale >= SectorNameAllSelectedScale) || options.HasFlag(MapOptions.SectorsAll));
            subsectorNames.visible = ((scale >= SubsectorNameMinScale) && (scale <= SubsectorNameMaxScale) && ((options & MapOptions.SectorsMask) != 0));

            worlds.visible = (scale >= WorldMinScale);
            pseudoRandomStars.visible = (PseudoRandomStarsMinScale <= scale) && (scale <= PseudoRandomStarsMaxScale);
            showRifts = (scale <= PseudoRandomStarsMaxScale || style == Style.Candy);

            t5AllegianceCodes = scale >= T5AllegianceCodeMinScale;

            float logscale = (float)Math.Log(scale, 2.0);
            riftOpacity = ScaleInterpolate(0f, 0.85f, scale, 1/4f, 4f);

            deepBackgroundOpacity = ScaleInterpolate(1f, 0f, scale, 1/8f, 2f);

            macroRoutes.visible = (scale >= MacroRouteMinScale) && (scale <= MacroRouteMaxScale);
            macroNames.visible = (scale >= MacroLabelMinScale) && (scale <= MacroLabelMaxScale);
            megaNames.visible = scale <= MegaLabelMaxScale && ((options & MapOptions.NamesMask) != 0);
            showMicroNames = ((scale >= MicroNameMinScale) && ((options & MapOptions.NamesMask) != 0));
            capitals.visible = (scale >= MacroWorldsMinScale) && (scale <= MacroWorldsMaxScale);

            hexStyle = (((options & MapOptions.ForceHexes) == 0) && (scale < ParsecHexMinScale))
                ? HexStyle.Square
                : HexStyle.Hex;
            microBorderStyle = hexStyle == HexStyle.Square ? MicroBorderStyle.Square : MicroBorderStyle.Hex;

            macroBorders.visible = (scale >= MacroBorderMinScale) && (scale < MicroBorderMinScale) && ((options & MapOptions.BordersMask) != 0);
            microBorders.visible = (scale >= MicroBorderMinScale) && ((options & MapOptions.BordersMask) != 0);
            fillMicroBorders = microBorders.visible && options.HasFlag(MapOptions.FilledBorders);
            microRoutes.visible = (scale >= RouteMinScale);

            worldDetails = !worlds.visible ? WorldDetails.None :
                (scale < WorldBasicMinScale) ? WorldDetails.Dotmap :
                (scale < WorldFullMinScale) ? WorldDetails.Atlas :
                WorldDetails.Poster;

            showWorldDetailColors = worldDetails == WorldDetails.Poster && options.HasFlag(MapOptions.WorldColors);

            lowerCaseAllegiance = (scale < WorldFullMinScale);

            worlds.textBackgroundStyle = TextBackgroundStyle.Rectangle;

            hexCoordinateStyle = HexCoordinateStyle.Sector;
            numberAllHexes = false;

            if (scale < WorldFullMinScale)
            {
                // Atlas-style

                const float x = 0.225f;
                const float y = 0.125f;

                BaseTopPosition.X = -x;
                BaseTopPosition.Y = -y;
                BaseBottomPosition.X = -x;
                BaseBottomPosition.Y = y;
                GasGiantPosition.X = x;
                GasGiantPosition.Y = -y;
                AllegiancePosition.X = x;
                AllegiancePosition.Y = y;

                BaseMiddlePosition.X = options.HasFlag(MapOptions.ForceHexes) ? -0.35f : -0.2f;
                BaseMiddlePosition.Y = 0;
                StarportPosition.X = 0.0f;
                StarportPosition.Y = -0.24f;
                worlds.position.X = 0.0f;
                worlds.position.Y = 0.4f;
            }
            else
            {
                // Poster-style

                const float x = 0.25f;
                const float y = 0.18f;

                BaseTopPosition.X = -x;
                BaseTopPosition.Y = -y;
                BaseBottomPosition.X = -x;
                BaseBottomPosition.Y = y;
                GasGiantPosition.X = x;
                GasGiantPosition.Y = -y;
                AllegiancePosition.X = x;
                AllegiancePosition.Y = y;

                BaseMiddlePosition.X = -0.35f;
                BaseMiddlePosition.Y = 0f;
                StarportPosition.X = 0f;
                StarportPosition.Y = -0.225f;
                worlds.position.X = 0.0f;
                worlds.position.Y = 0.37f; // Don't hide hex bottom, leave room for UWP
            }

            if (scale >= WorldUwpMinScale)
            {
                worldDetails |= WorldDetails.Uwp;
                BaseBottomPosition.Y = 0.1f;
                BaseMiddlePosition.Y = (BaseBottomPosition.Y + BaseTopPosition.Y) / 2;
                AllegiancePosition.Y = 0.1f;
            }

            if (worlds.visible)
            {
                float fontScale = (scale <= 96f || style == Style.Candy) ? 1f : 96f / Math.Min((float)scale, 192f);

                worlds.fontInfo = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.2f : 0.15f * fontScale, XFontStyle.Bold);
                wingdingFont = new FontInfo("Wingdings", scale < WorldFullMinScale ? 0.2f : 0.175f * fontScale);
                glyphFont = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.175f : 0.15f * fontScale, XFontStyle.Bold);
                hexNumber.fontInfo = new FontInfo(DEFAULT_FONT, 0.1f * fontScale);
                worlds.smallFontInfo = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.2f : 0.1f * fontScale, XFontStyle.Regular);
                worlds.largeFontInfo = worlds.fontInfo;
                starportFont = (scale < WorldFullMinScale) ? worlds.smallFontInfo : worlds.fontInfo;
            }

            sectorName.fontInfo = new FontInfo(DEFAULT_FONT, 5.5f);
            subsectorNames.fontInfo = new FontInfo(DEFAULT_FONT, 1.5f);

            microBorders.fontInfo = new FontInfo(DEFAULT_FONT, (scale == MicroNameMinScale) ? 0.6f : 0.25f, XFontStyle.Bold);
            microBorders.smallFontInfo = new FontInfo(DEFAULT_FONT, 0.15f, XFontStyle.Bold);
            microBorders.largeFontInfo = new FontInfo(DEFAULT_FONT, 0.75f, XFontStyle.Bold);

            macroNames.fontInfo = new FontInfo(DEFAULT_FONT, 8f / 1.4f, XFontStyle.Bold);
            macroNames.smallFontInfo = new FontInfo(DEFAULT_FONT, 5f / 1.4f, XFontStyle.Regular);
            macroNames.mediumFontInfo = new FontInfo(DEFAULT_FONT, 6.5f / 1.4f, XFontStyle.Italic);

            float megaNameScaleFactor = 1.0f * onePixel;
            megaNames.fontInfo = new FontInfo(DEFAULT_FONT, 24f * megaNameScaleFactor, XFontStyle.Bold);
            megaNames.mediumFontInfo = new FontInfo(DEFAULT_FONT, 22f * megaNameScaleFactor, XFontStyle.Regular);
            megaNames.smallFontInfo = new FontInfo(DEFAULT_FONT, 20f * megaNameScaleFactor, XFontStyle.Italic);

            capitals.fillColor = Color.Wheat;
            capitals.textColor = Color.Red;
            blueZone.pen.color = Color.Blue;
            amberZone.pen.color = Color.Gold;
            redZone.pen.color = Color.Red;
            macroBorders.pen.color = Color.Red;
            macroRoutes.pen.color = Color.White;
            microBorders.pen.color = Color.Gray;
            Color gridColor = Color.FromArgb(ScaleInterpolate(0, 255, scale, SectorGridMinScale, SectorGridFullScale), Color.Gray);
            microRoutes.pen.color = Color.Gray;

            Color foregroundColor = Color.White;
            backgroundColor = Color.Black;
            Color lightColor = Color.LightGray;
            Color darkColor = Color.DarkGray;
            Color dimColor = Color.DimGray;
            Color highlightColor = Color.Red;
            microBorders.textColor = Color.Gold;
            worldWater.fillColor = Color.DeepSkyBlue;
            worldNoWater.fillColor = Color.White;
            worldNoWater.pen.color = Color.Empty;

            parsecGrid.pen = new PenInfo(gridColor, onePixel);
            subsectorGrid.pen = new PenInfo(gridColor, onePixel * 2);
            sectorGrid.pen = new PenInfo(gridColor, (subsectorGrid.visible ? 4 : 2) * onePixel);
            worldWater.pen = new PenInfo(Color.Empty, Math.Max(0.01f, onePixel));

            microBorders.textStyle.Rotation = 0;
            microBorders.textStyle.Translation = new PointF(0, 0);
            microBorders.textStyle.Scale = new SizeF(1.0f, 1.0f);
            microBorders.textStyle.Uppercase = false;

            sectorName.textStyle.Rotation = -50; // degrees
            sectorName.textStyle.Translation = new PointF(0, 0);
            sectorName.textStyle.Scale = new SizeF(0.75f, 1.0f);
            sectorName.textStyle.Uppercase = false;
            sectorName.textStyle.Wrap = true;

            subsectorNames.textStyle = sectorName.textStyle;

            worlds.textStyle.Rotation = 0;
            worlds.textStyle.Scale = new SizeF(1.0f, 1.0f);
            worlds.textStyle.Translation = worlds.position;
            worlds.textStyle.Uppercase = false;

            useBackgroundImage = false;
            useGalaxyImage = deepBackgroundOpacity > 0.0f;
            useWorldImages = false;

            // Cap pen widths when zooming in
            float penScale = (scale <= 64) ? 1f : (64f / (float)scale);

            float borderPenWidth =
                (scale < MicroBorderMinScale) ? 1 : // When rendering vector borders
                (scale < ParsecMinScale) ? 1 :      // When not rendering "hexes"
                0.16f * penScale; // ... but cut in half by clipping

            float routePenWidth =
                scale <= 16 ? 0.2f :
                0.08f * penScale;

            microBorders.pen.width = borderPenWidth;
            macroBorders.pen.width = borderPenWidth;
            microRoutes.pen.width = routePenWidth;

            amberZone.pen.width = redZone.pen.width = blueZone.pen.width = 0.05f * penScale;

            macroRoutes.pen.width = borderPenWidth;
            macroRoutes.pen.DashStyle = XDashStyle.Dash;

            switch (style)
            {
                case Style.Poster:
                    {
                        // This is the default - no changes
                        break;
                    }
                case Style.Atlas:
                    {
                        grayscale = true;
                        lightBackground = true;

                        capitals.fillColor = Color.DarkGray;
                        capitals.textColor = Color.Black;
                        amberZone.pen.color = Color.LightGray;
                        blueZone.pen.color = Color.Gray; // TODO: make dashed
                        redZone.pen.color = Color.Black;
                        macroBorders.pen.color = Color.Black;
                        macroRoutes.pen.color = Color.Gray;
                        microBorders.pen.color = Color.Black;
                        microRoutes.pen.color = Color.Gray;

                        foregroundColor = Color.Black;
                        backgroundColor = Color.White;
                        lightColor = Color.DarkGray;
                        darkColor = Color.DarkGray;
                        dimColor = Color.LightGray;
                        highlightColor = Color.Gray;
                        microBorders.textColor = Color.Gray;
                        worldWater.fillColor = Color.Black;
                        worldNoWater.fillColor = Color.Empty;

                        worldNoWater.fillColor = Color.White;
                        worldNoWater.pen = new PenInfo(Color.Black, onePixel);

                        riftOpacity = Math.Min(riftOpacity, 0.70f);

                        showWorldDetailColors = false;

                        break;
                    }
                case Style.FASA:
                    {
                        useGalaxyImage = false;
                        deepBackgroundOpacity = 0f;
                        riftOpacity = 0;

                        Color inkColor = Color.FromArgb(0x5C, 0x40, 0x33);

                        foregroundColor = inkColor;
                        backgroundColor = Color.White;

                        grayscale = true; // TODO: Tweak to be "monochrome"
                        lightBackground = true;

                        capitals.fillColor = inkColor;
                        capitals.textColor = inkColor;
                        amberZone.pen.color = inkColor;
                        amberZone.pen.width = onePixel * 2;
                        blueZone.pen.color = inkColor; // TODO: make dashed
                        redZone.pen.color = Color.Empty;
                        redZone.fillColor = Color.FromArgb(0x80, inkColor);

                        macroBorders.pen.color = inkColor;
                        macroRoutes.pen.color = inkColor;

                        microBorders.pen.color = inkColor;
                        microBorders.pen.width = onePixel * 2;
                        microBorders.fontInfo.size *= 0.6f;
                        microBorders.fontInfo.style = XFontStyle.Regular;

                        microRoutes.pen.color = inkColor;

                        lightColor = Color.FromArgb(0x80, inkColor);
                        darkColor = inkColor;
                        dimColor = inkColor;
                        highlightColor = inkColor;
                        microBorders.textColor = inkColor;
                        hexStyle = HexStyle.Hex;
                        microBorderStyle = MicroBorderStyle.Curve;

                        parsecGrid.pen.color = lightColor;
                        sectorGrid.pen.color = lightColor;
                        subsectorGrid.pen.color = lightColor;

                        worldWater.fillColor = inkColor;
                        worldNoWater.fillColor = inkColor;
                        worldWater.pen.color = Color.Empty;
                        worldNoWater.pen.color = Color.Empty;

                        showWorldDetailColors = false;

                        worldDetails = worldDetails & ~WorldDetails.Starport;
                        worldDetails = worldDetails & ~WorldDetails.Allegiance;
                        worldDetails = worldDetails & ~WorldDetails.Bases;
                        worldDetails = worldDetails & ~WorldDetails.GasGiant;
                        worldDetails = worldDetails & ~WorldDetails.Highlight;
                        worlds.fontInfo.size *= 0.85f;
                        worlds.textStyle.Translation = new PointF(0, 0.25f);

                        numberAllHexes = true;
                        hexCoordinateStyle = HexCoordinateStyle.Subsector;
                        overrideLineStyle = LineStyle.Solid;

                        break;
                    }
                case Style.Print:
                    {
                        lightBackground = true;

                        foregroundColor = Color.Black;
                        backgroundColor = Color.White;
                        lightColor = Color.DarkGray;
                        darkColor = Color.DarkGray;
                        dimColor = Color.LightGray;
                        microRoutes.pen.color = Color.Gray;

                        microBorders.textColor = Color.Brown;

                        amberZone.pen.color = Color.Gold;
                        worldNoWater.fillColor = Color.White;
                        worldNoWater.pen = new PenInfo(Color.Black, onePixel);

                        riftOpacity = Math.Min(riftOpacity, 0.70f);

                        break;
                    }
                case Style.Draft:
                    {
                        int inkOpacity = 0xB0;

                        useGalaxyImage = false;
                        lightBackground = true;

                        deepBackgroundOpacity = 0f;

                        backgroundColor = Color.AntiqueWhite;
                        foregroundColor = Color.FromArgb(inkOpacity, Color.Black);
                        highlightColor = Color.FromArgb(inkOpacity, Color.Red);

                        lightColor = Color.FromArgb(inkOpacity, Color.DarkCyan);
                        darkColor = Color.FromArgb(inkOpacity, Color.Black);
                        dimColor = Color.FromArgb(inkOpacity / 2, Color.Black);

                        subsectorGrid.pen.color = Color.FromArgb(inkOpacity, Color.Firebrick);

                        const string FONT_NAME = "Comic Sans MS";
                        worlds.fontInfo.name = FONT_NAME;
                        worlds.smallFontInfo.name = FONT_NAME;
                        starportFont.name = FONT_NAME;
                        worlds.largeFontInfo.name = FONT_NAME;
                        worlds.largeFontInfo.size = worlds.fontInfo.size * 1.25f;
                        worlds.fontInfo.size *= 0.8f;

                        macroNames.fontInfo.name = FONT_NAME;
                        macroNames.mediumFontInfo.name = FONT_NAME;
                        macroNames.smallFontInfo.name = FONT_NAME;
                        megaNames.fontInfo.name = FONT_NAME;
                        megaNames.mediumFontInfo.name = FONT_NAME;
                        megaNames.smallFontInfo.name = FONT_NAME;
                        microBorders.smallFontInfo.name = FONT_NAME;
                        microBorders.largeFontInfo.name = FONT_NAME;
                        microBorders.fontInfo.name = FONT_NAME;
                        macroBorders.fontInfo.name = FONT_NAME;
                        macroRoutes.fontInfo.name = FONT_NAME;
                        capitals.fontInfo.name = FONT_NAME;
                        macroBorders.smallFontInfo.name = FONT_NAME;

                        microBorders.textStyle.Uppercase = true;

                        sectorName.textStyle.Uppercase = true;
                        subsectorNames.textStyle.Uppercase = true;

                        // TODO: Render small, around edges
                        subsectorNames.visible = false;

                        worlds.textStyle.Uppercase = true;

                        // TODO: Decide on this. It's nice to not overwrite the parsec grid, but
                        // it looks very cluttered, especially amber/red zones.
                        worlds.textBackgroundStyle = TextBackgroundStyle.None;

                        worldDetails = worldDetails & ~WorldDetails.Allegiance;

                        subsectorNames.fontInfo.name = FONT_NAME;
                        sectorName.fontInfo.name = FONT_NAME;

                        worlds.largeFontInfo.style |= XFontStyle.Underline;

                        microBorders.pen.width = onePixel * 4;
                        microBorders.pen.dashStyle = XDashStyle.Dot;

                        worldNoWater.fillColor = foregroundColor;
                        worldWater.fillColor = Color.Empty;
                        worldWater.pen = new PenInfo(foregroundColor, onePixel * 2);

                        amberZone.pen.color = foregroundColor;
                        amberZone.pen.width = onePixel;
                        redZone.pen.width = onePixel * 2;

                        microRoutes.pen.color = Color.Gray;

                        parsecGrid.pen.color = lightColor;
                        microBorders.textColor = Color.FromArgb(inkOpacity, Color.Brown);

                        riftOpacity = Math.Min(riftOpacity, 0.30f);

                        numberAllHexes = true;

                        break;
                    }
                case Style.Candy:
                    {
                        useWorldImages = true;
                        pseudoRandomStars.visible = false;

                        useBackgroundImage = deepBackgroundOpacity < 0.5f;

                        hexStyle = HexStyle.None;
                        microBorderStyle = MicroBorderStyle.Curve;

                        sectorGrid.visible = sectorGrid.visible && (scale >= 4);
                        subsectorGrid.visible = subsectorGrid.visible && (scale >= 32);
                        parsecGrid.visible = false;

                        subsectorGrid.pen.width = 0.03f * (64.0f / (float)scale);
                        subsectorGrid.pen.DashPattern = new double[] { 10.0, 8.0 };

                        sectorGrid.pen.width = 0.03f * (64.0f / (float)scale);
                        sectorGrid.pen.DashPattern = new double[] { 10.0, 8.0 };

                        worlds.textBackgroundStyle = TextBackgroundStyle.Shadow;

                        worldDetails = worldDetails
                            & ~WorldDetails.Starport & ~WorldDetails.Allegiance & ~WorldDetails.Bases & ~WorldDetails.Hex;

                        if (scale < CandyMinWorldNameScale)
                            worldDetails = worldDetails & ~WorldDetails.KeyNames & ~WorldDetails.AllNames;
                        if (scale < CandyMinUwpScale)
                            worldDetails = worldDetails & ~WorldDetails.Uwp;

                        amberZone.pen.color = Color.Goldenrod;

                        sectorName.textStyle.Rotation = 0;
                        sectorName.textStyle.Translation = new PointF(0, -0.25f);
                        sectorName.textStyle.Scale = new SizeF(0.5f, 0.25f);
                        sectorName.textStyle.Uppercase = true;

                        subsectorNames.textStyle.Rotation = 0;
                        subsectorNames.textStyle.Translation = new PointF(0, -0.25f);
                        subsectorNames.textStyle.Scale = new SizeF(0.3f, 0.15f); // Expand
                        subsectorNames.textStyle.Uppercase = true;

                        microBorders.textStyle.Rotation = 0;
                        microBorders.textStyle.Translation = new PointF(0, 0.25f);
                        microBorders.textStyle.Scale = new SizeF(1.0f, 0.5f); // Expand
                        microBorders.textStyle.Uppercase = true;

                        microBorders.pen.color = Color.FromArgb(128, Color.Red);

                        worlds.textStyle.Rotation = 0;
                        worlds.textStyle.Scale = new SizeF(1f, 0.5f); // Expand
                        worlds.textStyle.Translation = new PointF(0, 0);
                        worlds.textStyle.Uppercase = true;

                        if (scale > CandyMaxWorldRelativeScale)
                            hexContentScale = CandyMaxWorldRelativeScale / (float)scale;

                        break;
                    }
            }

            sectorName.textColor = scale < 16 ? foregroundColor :
                scale < 48 ? darkColor : dimColor;
            subsectorNames.textColor = scale < 16 ? foregroundColor :
                scale < 48 ? darkColor : dimColor;

            if (style == Style.Candy)
            {
                subsectorNames.textColor = sectorName.textColor = Color.FromArgb(128, Color.Goldenrod);

                amberZone.pen.width = redZone.pen.width = blueZone.pen.width = 0.035f;

                microRoutes.pen.width = scale < CandyMaxRouteRelativeScale ? routePenWidth : routePenWidth / 2;
                macroBorders.pen.width = scale < CandyMaxBorderRelativeScale ? borderPenWidth : borderPenWidth / 4;
                microBorders.pen.width = scale < CandyMaxBorderRelativeScale ? borderPenWidth : borderPenWidth / 4;
            }

            preferredMimeType = (style == Style.Candy)
                ? System.Net.Mime.MediaTypeNames.Image.Jpeg
                : Util.MediaTypeName_Image_Png;

            pseudoRandomStars.fillColor = foregroundColor;

            megaNames.textColor = foregroundColor;
            megaNames.textHighlightColor = highlightColor;

            macroNames.textColor = foregroundColor;
            macroNames.textHighlightColor = highlightColor;

            macroRoutes.textColor = foregroundColor;
            macroRoutes.textHighlightColor = highlightColor;

            worlds.textColor = foregroundColor;
            worlds.textHighlightColor = highlightColor;

            hexNumber.textColor = lightColor;
            imageBorderColor = lightColor;

            placeholder.content = "*";
            placeholder.fontInfo = new FontInfo("Georgia", 0.6f);
            placeholder.textColor = foregroundColor;
            placeholder.position = new PointF(0, 0.17f);
        }
예제 #3
0
        public Stylesheet(double scale, MapOptions options, Style style)
        {
            grayscale              = false;
            subsectorGrid.visible  = ((scale >= SubsectorsMinScale) && options.HasFlag(MapOptions.SubsectorGrid));
            sectorGrid.visible     = ((scale >= SectorGridMinScale) && options.HasFlag(MapOptions.SectorGrid));
            parsecGrid.visible     = (scale >= ParsecMinScale);
            showSomeSectorNames    = ((scale >= SectorNameMinScale) && (scale <= SectorNameMaxScale) && ((options & MapOptions.SectorsMask) != 0));
            showAllSectorNames     = showSomeSectorNames && ((scale >= SectorNameAllSelectedScale) || options.HasFlag(MapOptions.SectorsAll));
            subsectorNames.visible = ((scale >= SubsectorNameMinScale) && (scale <= SubsectorNameMaxScale) && ((options & MapOptions.SectorsMask) != 0));

            worlds.visible            = (scale >= WorldMinScale);
            pseudoRandomStars.visible = (PseudoRandomStarsMinScale <= scale) && (scale <= PseudoRandomStarsMaxScale);
            showRifts = (scale <= PseudoRandomStarsMaxScale || style == Style.Candy);

            float logscale = (float)Math.Log(scale, 2.0);

            riftOpacity           = Util.Clamp((logscale - -2f) / (2f - -2f), 0.0f, 1.0f) * 0.85f;
            deepBackgroundOpacity = 1.0f - Util.Clamp((logscale - -3f) / (0f - -3f), 0f, 1f);

            macroRoutes.visible = (scale >= MacroRouteMinScale) && (scale <= MacroRouteMaxScale);
            macroNames.visible  = (scale >= MacroLabelMinScale) && (scale <= MacroLabelMaxScale);
            showMicroNames      = ((scale >= MicroNameMinScale) && ((options & MapOptions.NamesMask) != 0));
            capitals.visible    = (scale >= MacroWorldsMinScale) && (scale <= MacroWorldsMaxScale);

            microBorderStyle = (((options & MapOptions.ForceHexes) == 0) && (scale < ParsecHexMinScale))
                ? MicroBorderStyle.Square
                : MicroBorderStyle.Hex;

            macroBorders.visible = (scale >= MacroBorderMinScale) && (scale < MicroBorderMinScale) && ((options & MapOptions.BordersMask) != 0);
            microBorders.visible = (scale >= MicroBorderMinScale) && ((options & MapOptions.BordersMask) != 0);
            fillMicroBorders     = microBorders.visible && options.HasFlag(MapOptions.FilledBorders);
            microRoutes.visible  = (scale >= RouteMinScale);

            worldDetails = !worlds.visible ? 0 :
                           (scale < WorldBasicMinScale) ? WorldDetails.Dotmap :
                           (scale < WorldFullMinScale) ? WorldDetails.Atlas :
                           WorldDetails.Poster;

            showWorldDetailColors = worldDetails == WorldDetails.Poster && options.HasFlag(MapOptions.WorldColors);

            lowerCaseAllegiance = (scale < WorldFullMinScale);

            worlds.textBackgroundStyle = TextBackgroundStyle.Rectangle;

            hexCoordinateStyle = HexCoordinateStyle.Sector;

            if (scale < WorldFullMinScale)
            {
                // Atlas-style

                const float x = 0.225f;
                const float y = 0.125f;

                BaseTopPosition.X    = -x;
                BaseTopPosition.Y    = -y;
                BaseBottomPosition.X = -x;
                BaseBottomPosition.Y = y;
                GasGiantPosition.X   = x;
                GasGiantPosition.Y   = -y;
                AllegiancePosition.X = x;
                AllegiancePosition.Y = y;

                BaseMiddlePosition.X = options.HasFlag(MapOptions.ForceHexes) ? -0.35f : -0.2f;
                BaseMiddlePosition.Y = 0;
                StarportPosition.X   = 0.0f;
                StarportPosition.Y   = -0.24f;
                worlds.position.X    = 0.0f;
                worlds.position.Y    = 0.4f;
            }
            else
            {
                // Poster-style

                const float x = 0.25f;
                const float y = 0.18f;

                BaseTopPosition.X    = -x;
                BaseTopPosition.Y    = -y;
                BaseBottomPosition.X = -x;
                BaseBottomPosition.Y = y;
                GasGiantPosition.X   = x;
                GasGiantPosition.Y   = -y;
                AllegiancePosition.X = x;
                AllegiancePosition.Y = y;

                BaseMiddlePosition.X = -0.35f;
                BaseMiddlePosition.Y = 0f;
                StarportPosition.X   = 0f;
                StarportPosition.Y   = -0.225f;
                worlds.position.X    = 0.0f;
                worlds.position.Y    = 0.37f; // Don't hide hex bottom, leave room for UWP
            }

            if (scale >= WorldUwpMinScale)
            {
                worldDetails        |= WorldDetails.Uwp;
                BaseBottomPosition.Y = 0.1f;
                BaseMiddlePosition.Y = (BaseBottomPosition.Y + BaseTopPosition.Y) / 2;
                AllegiancePosition.Y = 0.1f;
            }

            if (worlds.visible)
            {
                float fontScale = (scale <= 96f || style == Style.Candy) ? 1f : 96f / (float)scale;

                worlds.fontInfo      = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.2f : 0.15f * fontScale, XFontStyle.Bold);
                wingdingFont         = new FontInfo("Wingdings", scale < WorldFullMinScale ? 0.2f : 0.175f * fontScale);
                glyphFont            = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.175f : 0.15f * fontScale, XFontStyle.Bold);
                hexNumber.fontInfo   = new FontInfo(DEFAULT_FONT, 0.1f * fontScale);
                worlds.smallFontInfo = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.2f : 0.1f * fontScale, XFontStyle.Regular);
                starportFont         = (scale < WorldFullMinScale) ? worlds.smallFontInfo : worlds.fontInfo;
            }

            sectorName.fontInfo     = new FontInfo(DEFAULT_FONT, 5.5f);
            subsectorNames.fontInfo = new FontInfo(DEFAULT_FONT, 1.5f);

            microBorders.fontInfo      = new FontInfo(DEFAULT_FONT, (scale == MicroNameMinScale) ? 0.6f : 0.25f, XFontStyle.Bold);
            microBorders.smallFontInfo = new FontInfo(DEFAULT_FONT, 0.15f, XFontStyle.Bold);
            microBorders.largeFontInfo = new FontInfo(DEFAULT_FONT, 0.75f, XFontStyle.Bold);

            macroNames.fontInfo      = new FontInfo(DEFAULT_FONT, 8f / 1.4f, XFontStyle.Bold);
            macroNames.smallFontInfo = new FontInfo(DEFAULT_FONT, 5f / 1.4f, XFontStyle.Regular);


            capitals.fillColor     = Color.Wheat;
            capitals.textColor     = Color.Red;
            blueZone.pen.color     = Color.Blue;
            amberZone.pen.color    = Color.Gold;
            redZone.pen.color      = Color.Red;
            macroBorders.pen.color = Color.Red;
            macroRoutes.pen.color  = Color.White;
            microBorders.pen.color = Color.Gray;
            Color gridColor = Color.Gray;

            microRoutes.pen.color = Color.Green;

            Color foregroundColor = Color.White;

            backgroundColor = Color.Black;
            Color lightColor     = Color.LightGray;
            Color darkColor      = Color.DarkGray;
            Color dimColor       = Color.DimGray;
            Color highlightColor = Color.Red;

            microBorders.textColor = Color.Gold;
            worldWater.fillColor   = Color.DeepSkyBlue;
            worldNoWater.fillColor = Color.White;
            worldNoWater.pen.color = Color.Empty;

            float onePixel = 1f / (float)scale;

            parsecGrid.pen    = new PenInfo(gridColor, onePixel);
            subsectorGrid.pen = new PenInfo(gridColor, onePixel * 2);
            sectorGrid.pen    = new PenInfo(gridColor, (subsectorGrid.visible ? 4 : 2) * onePixel);

            microBorders.textStyle.Rotation    = 0;
            microBorders.textStyle.Translation = new PointF(0, 0);
            microBorders.textStyle.Scale       = new SizeF(1.0f, 1.0f);
            microBorders.textStyle.Uppercase   = false;

            sectorName.textStyle.Rotation    = -50;
            sectorName.textStyle.Translation = new PointF(0, 0);
            sectorName.textStyle.Scale       = new SizeF(0.75f, 1.0f);
            sectorName.textStyle.Uppercase   = false;
            sectorName.textStyle.Wrap        = true;

            subsectorNames.textStyle = sectorName.textStyle;

            worlds.textStyle.Rotation    = 0;
            worlds.textStyle.Scale       = new SizeF(1.0f, 1.0f);
            worlds.textStyle.Translation = worlds.position;
            worlds.textStyle.Uppercase   = false;

            useBackgroundImage = false;
            useGalaxyImage     = false;
            useWorldImages     = false;

            switch (style)
            {
            case Style.Poster:
            {
                // This is the default - no changes
                useGalaxyImage = deepBackgroundOpacity > 0.0f;
                break;
            }

            case Style.Atlas:
            {
                deepBackgroundOpacity = 0f;

                grayscale              = true;
                capitals.fillColor     = Color.DarkGray;
                capitals.textColor     = Color.Black;
                amberZone.pen.color    = Color.LightGray;
                blueZone.pen.color     = Color.Gray;     // TODO: make dashed
                redZone.pen.color      = Color.Black;
                macroBorders.pen.color = Color.Black;
                macroRoutes.pen.color  = Color.Gray;
                microBorders.pen.color = Color.Black;
                microRoutes.pen.color  = Color.Gray;

                foregroundColor        = Color.Black;
                backgroundColor        = Color.White;
                lightColor             = Color.DarkGray;
                darkColor              = Color.DarkGray;
                dimColor               = Color.LightGray;
                highlightColor         = Color.Gray;
                microBorders.textColor = Color.Gray;
                worldWater.fillColor   = Color.Black;
                worldNoWater.fillColor = Color.Empty;

                worldNoWater.fillColor = Color.White;
                worldNoWater.pen       = new PenInfo(Color.Black, onePixel);

                riftOpacity = Math.Min(riftOpacity, 0.70f);

                showWorldDetailColors = false;

                break;
            }

            case Style.Print:
            {
                deepBackgroundOpacity = 0f;

                foregroundColor       = Color.Black;
                backgroundColor       = Color.White;
                lightColor            = Color.DarkGray;
                darkColor             = Color.DarkGray;
                dimColor              = Color.LightGray;
                microRoutes.pen.color = Color.Gray;

                microBorders.textColor = Color.Brown;

                amberZone.pen.color    = Color.Gold;
                worldNoWater.fillColor = Color.White;
                worldNoWater.pen       = new PenInfo(Color.Black, onePixel);

                riftOpacity = Math.Min(riftOpacity, 0.70f);

                break;
            }

            case Style.Candy:
            {
                useWorldImages            = true;
                pseudoRandomStars.visible = false;

                useBackgroundImage = deepBackgroundOpacity < 1.0f;
                useGalaxyImage     = deepBackgroundOpacity > 0.0f;


                microBorderStyle = MicroBorderStyle.Curve;

                sectorGrid.visible    = sectorGrid.visible && (scale >= 4 && scale < 32);
                subsectorGrid.visible = subsectorGrid.visible && (scale >= 32);
                parsecGrid.visible    = false;

                subsectorGrid.pen.width       = 0.03f * (64.0f / (float)scale);
                subsectorGrid.pen.DashPattern = new double[] { 10.0, 8.0 };

                sectorGrid.pen.width       = 0.03f * (64.0f / (float)scale);
                sectorGrid.pen.DashPattern = new double[] { 10.0, 8.0 };

                worlds.textBackgroundStyle = TextBackgroundStyle.Shadow;

                worldDetails = worldDetails
                               & ~WorldDetails.Starport & ~WorldDetails.Allegiance & ~WorldDetails.Bases & ~WorldDetails.Hex;

                if (scale < CandyMinWorldNameScale)
                {
                    worldDetails = worldDetails & ~WorldDetails.KeyNames & ~WorldDetails.AllNames;
                }
                if (scale < CandyMinUwpScale)
                {
                    worldDetails = worldDetails & ~WorldDetails.Uwp;
                }

                amberZone.pen.color = Color.Goldenrod;

                sectorName.textStyle.Rotation    = 0;
                sectorName.textStyle.Translation = new PointF(0, -0.25f);
                sectorName.textStyle.Scale       = new SizeF(0.5f, 0.25f);
                sectorName.textStyle.Uppercase   = true;

                subsectorNames.textStyle.Rotation    = 0;
                subsectorNames.textStyle.Translation = new PointF(0, -0.25f);
                subsectorNames.textStyle.Scale       = new SizeF(0.3f, 0.15f);   // Expand
                subsectorNames.textStyle.Uppercase   = true;

                microBorders.textStyle.Rotation    = 0;
                microBorders.textStyle.Translation = new PointF(0, 0.25f);
                microBorders.textStyle.Scale       = new SizeF(1.0f, 0.5f);   // Expand
                microBorders.textStyle.Uppercase   = true;

                microBorders.pen.color = Color.FromArgb(128, Color.Red);

                worlds.textStyle.Rotation    = 0;
                worlds.textStyle.Scale       = new SizeF(1f, 0.5f);   // Expand
                worlds.textStyle.Translation = new PointF(0, 0);
                worlds.textStyle.Uppercase   = true;

                if (scale > CandyMaxWorldRelativeScale)
                {
                    hexContentScale = CandyMaxWorldRelativeScale / (float)scale;
                }

                break;
            }
            }

            sectorName.textColor = scale < 16 ? foregroundColor :
                                   scale < 48 ? darkColor : dimColor;
            subsectorNames.textColor = scale < 16 ? foregroundColor :
                                       scale < 48 ? darkColor : dimColor;

            // Cap pen widths when zooming in
            float penScale = (scale <= 64) ? 1f : (64f / (float)scale);

            float borderPenWidth =
                (scale < MicroBorderMinScale) ? 1 : // When rendering vector borders
                (scale < ParsecMinScale) ? 1 :      // When not rendering "hexes"
                0.16f * penScale;                   // ... but cut in half by clipping

            float routePenWidth =
                scale <= 16 ? 0.2f :
                0.08f * penScale;

            microBorders.pen.width = borderPenWidth;
            macroBorders.pen.width = borderPenWidth;
            microRoutes.pen.width  = routePenWidth;

            amberZone.pen.width = redZone.pen.width = blueZone.pen.width = 0.05f * penScale;

            macroRoutes.pen.width     = borderPenWidth;
            macroRoutes.pen.DashStyle = XDashStyle.Dash;

            if (style == Style.Candy)
            {
                subsectorNames.textColor = sectorName.textColor = Color.FromArgb(128, Color.Goldenrod);

                amberZone.pen.width = redZone.pen.width = blueZone.pen.width = 0.035f;

                microRoutes.pen.width  = scale < CandyMaxRouteRelativeScale ? routePenWidth : routePenWidth / 2;
                macroBorders.pen.width = scale < CandyMaxBorderRelativeScale ? borderPenWidth : borderPenWidth / 4;
                microBorders.pen.width = scale < CandyMaxBorderRelativeScale ? borderPenWidth : borderPenWidth / 4;
            }

            preferredMimeType = (style == Style.Candy)
                ? System.Net.Mime.MediaTypeNames.Image.Jpeg
                : Util.MediaTypeName_Image_Png;

            pseudoRandomStars.fillColor = foregroundColor;

            macroNames.textColor          = foregroundColor;
            macroNames.textHighlightColor = highlightColor;

            macroRoutes.textColor          = foregroundColor;
            macroRoutes.textHighlightColor = highlightColor;

            worlds.textColor          = foregroundColor;
            worlds.textHighlightColor = highlightColor;

            hexNumber.textColor = lightColor;
            imageBorderColor    = lightColor;
        }
예제 #4
0
        private const float WorldUwpMinScale = 96; // Above this: UWP shown above name

        #endregion Fields

        #region Constructors

        public Stylesheet(double scale, MapOptions options, Style style)
        {
            grayscale = false;
            subsectorGrid.visible = ((scale >= SubsectorsMinScale) && options.HasFlag(MapOptions.SubsectorGrid));
            sectorGrid.visible = ((scale >= SectorGridMinScale) && options.HasFlag(MapOptions.SectorGrid));
            parsecGrid.visible = (scale >= ParsecMinScale);
            showSomeSectorNames = ((scale >= SectorNameMinScale) && (scale <= SectorNameMaxScale) && ((options & MapOptions.SectorsMask) != 0));
            showAllSectorNames = showSomeSectorNames && ((scale >= SectorNameAllSelectedScale) || options.HasFlag(MapOptions.SectorsAll));
            subsectorNames.visible = ((scale >= SubsectorNameMinScale) && (scale <= SubsectorNameMaxScale) && ((options & MapOptions.SectorsMask) != 0));

            worlds.visible = (scale >= WorldMinScale);
            pseudoRandomStars.visible = (PseudoRandomStarsMinScale <= scale) && (scale <= PseudoRandomStarsMaxScale);
            showRifts = (scale <= PseudoRandomStarsMaxScale || style == Style.Candy);

            float logscale = (float)Math.Log(scale, 2.0);
            riftOpacity = Util.Clamp((logscale - -2f) / (2f - -2f), 0.0f, 1.0f) * 0.85f;
            deepBackgroundOpacity = 1.0f - Util.Clamp((logscale - -3f) / (0f - -3f), 0f, 1f);

            macroRoutes.visible = (scale >= MacroRouteMinScale) && (scale <= MacroRouteMaxScale);
            macroNames.visible = (scale >= MacroLabelMinScale) && (scale <= MacroLabelMaxScale);
            showMicroNames = ((scale >= MicroNameMinScale) && ((options & MapOptions.NamesMask) != 0));
            capitals.visible = (scale >= MacroWorldsMinScale) && (scale <= MacroWorldsMaxScale);

            microBorderStyle = (((options & MapOptions.ForceHexes) == 0) && (scale < ParsecHexMinScale))
                ? MicroBorderStyle.Square
                : MicroBorderStyle.Hex;

            macroBorders.visible = (scale >= MacroBorderMinScale) && (scale < MicroBorderMinScale) && ((options & MapOptions.BordersMask) != 0);
            microBorders.visible = (scale >= MicroBorderMinScale) && ((options & MapOptions.BordersMask) != 0);
            fillMicroBorders = microBorders.visible && options.HasFlag(MapOptions.FilledBorders);
            microRoutes.visible = (scale >= RouteMinScale);

            worldDetails = !worlds.visible ? 0 :
                (scale < WorldBasicMinScale) ? WorldDetails.Dotmap :
                (scale < WorldFullMinScale) ? WorldDetails.Atlas :
                WorldDetails.Poster;

            showWorldDetailColors = worldDetails == WorldDetails.Poster && options.HasFlag(MapOptions.WorldColors);

            lowerCaseAllegiance = (scale < WorldFullMinScale);

            worlds.textBackgroundStyle = TextBackgroundStyle.Rectangle;

            hexCoordinateStyle = HexCoordinateStyle.Sector;

            if (scale < WorldFullMinScale)
            {
                // Atlas-style

                const float x = 0.225f;
                const float y = 0.125f;

                BaseTopPosition.X = -x;
                BaseTopPosition.Y = -y;
                BaseBottomPosition.X = -x;
                BaseBottomPosition.Y = y;
                GasGiantPosition.X = x;
                GasGiantPosition.Y = -y;
                AllegiancePosition.X = x;
                AllegiancePosition.Y = y;

                BaseMiddlePosition.X = options.HasFlag(MapOptions.ForceHexes) ? -0.35f : -0.2f;
                BaseMiddlePosition.Y = 0;
                StarportPosition.X = 0.0f;
                StarportPosition.Y = -0.24f;
                worlds.position.X = 0.0f;
                worlds.position.Y = 0.4f;
            }
            else
            {
                // Poster-style

                const float x = 0.25f;
                const float y = 0.18f;

                BaseTopPosition.X = -x;
                BaseTopPosition.Y = -y;
                BaseBottomPosition.X = -x;
                BaseBottomPosition.Y = y;
                GasGiantPosition.X = x;
                GasGiantPosition.Y = -y;
                AllegiancePosition.X = x;
                AllegiancePosition.Y = y;

                BaseMiddlePosition.X = -0.35f;
                BaseMiddlePosition.Y = 0f;
                StarportPosition.X = 0f;
                StarportPosition.Y = -0.225f;
                worlds.position.X = 0.0f;
                worlds.position.Y = 0.37f; // Don't hide hex bottom, leave room for UWP
            }

            if (scale >= WorldUwpMinScale)
            {
                worldDetails |= WorldDetails.Uwp;
                BaseBottomPosition.Y = 0.1f;
                BaseMiddlePosition.Y = (BaseBottomPosition.Y + BaseTopPosition.Y) / 2;
                AllegiancePosition.Y = 0.1f;
            }

            if (worlds.visible)
            {
                float fontScale = (scale <= 96f || style == Style.Candy) ? 1f : 96f / (float)scale;

                worlds.fontInfo = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.2f : 0.15f * fontScale, XFontStyle.Bold);
                wingdingFont = new FontInfo("Wingdings", scale < WorldFullMinScale ? 0.2f : 0.175f * fontScale);
                glyphFont = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.175f : 0.15f * fontScale, XFontStyle.Bold);
                hexNumber.fontInfo = new FontInfo(DEFAULT_FONT, 0.1f * fontScale);
                worlds.smallFontInfo = new FontInfo(DEFAULT_FONT, scale < WorldFullMinScale ? 0.2f : 0.1f * fontScale, XFontStyle.Regular);
                starportFont = (scale < WorldFullMinScale) ? worlds.smallFontInfo : worlds.fontInfo;
            }

            sectorName.fontInfo = new FontInfo(DEFAULT_FONT, 5.5f);
            subsectorNames.fontInfo = new FontInfo(DEFAULT_FONT, 1.5f);

            microBorders.fontInfo = new FontInfo(DEFAULT_FONT, (scale == MicroNameMinScale) ? 0.6f : 0.25f, XFontStyle.Bold);
            microBorders.smallFontInfo = new FontInfo(DEFAULT_FONT, 0.15f, XFontStyle.Bold);
            microBorders.largeFontInfo = new FontInfo(DEFAULT_FONT, 0.75f, XFontStyle.Bold);

            macroNames.fontInfo = new FontInfo(DEFAULT_FONT, 8f / 1.4f, XFontStyle.Bold);
            macroNames.smallFontInfo = new FontInfo(DEFAULT_FONT, 5f / 1.4f, XFontStyle.Regular);

            capitals.fillColor = Color.Wheat;
            capitals.textColor = Color.Red;
            blueZone.pen.color = Color.Blue;
            amberZone.pen.color = Color.Gold;
            redZone.pen.color = Color.Red;
            macroBorders.pen.color = Color.Red;
            macroRoutes.pen.color = Color.White;
            microBorders.pen.color = Color.Gray;
            Color gridColor = Color.Gray;
            microRoutes.pen.color = Color.Green;

            Color foregroundColor = Color.White;
            backgroundColor = Color.Black;
            Color lightColor = Color.LightGray;
            Color darkColor = Color.DarkGray;
            Color dimColor = Color.DimGray;
            Color highlightColor = Color.Red;
            microBorders.textColor = Color.Gold;
            worldWater.fillColor = Color.DeepSkyBlue;
            worldNoWater.fillColor = Color.White;
            worldNoWater.pen.color = Color.Empty;

            float onePixel = 1f / (float)scale;

            parsecGrid.pen = new PenInfo(gridColor, onePixel);
            subsectorGrid.pen = new PenInfo(gridColor, onePixel * 2);
            sectorGrid.pen = new PenInfo(gridColor, (subsectorGrid.visible ? 4 : 2) * onePixel);

            microBorders.textStyle.Rotation = 0;
            microBorders.textStyle.Translation = new PointF(0, 0);
            microBorders.textStyle.Scale = new SizeF(1.0f, 1.0f);
            microBorders.textStyle.Uppercase = false;

            sectorName.textStyle.Rotation = -50;
            sectorName.textStyle.Translation = new PointF(0, 0);
            sectorName.textStyle.Scale = new SizeF(0.75f, 1.0f);
            sectorName.textStyle.Uppercase = false;
            sectorName.textStyle.Wrap = true;

            subsectorNames.textStyle = sectorName.textStyle;

            worlds.textStyle.Rotation = 0;
            worlds.textStyle.Scale = new SizeF(1.0f, 1.0f);
            worlds.textStyle.Translation = worlds.position;
            worlds.textStyle.Uppercase = false;

            useBackgroundImage = false;
            useGalaxyImage = false;
            useWorldImages = false;

            switch (style)
            {
                case Style.Poster:
                    {
                        // This is the default - no changes
                        useGalaxyImage = deepBackgroundOpacity > 0.0f;
                        break;
                    }
                case Style.Atlas:
                    {
                        deepBackgroundOpacity = 0f;

                        grayscale = true;
                        capitals.fillColor = Color.DarkGray;
                        capitals.textColor = Color.Black;
                        amberZone.pen.color = Color.LightGray;
                        blueZone.pen.color = Color.Gray; // TODO: make dashed
                        redZone.pen.color = Color.Black;
                        macroBorders.pen.color = Color.Black;
                        macroRoutes.pen.color = Color.Gray;
                        microBorders.pen.color = Color.Black;
                        microRoutes.pen.color = Color.Gray;

                        foregroundColor = Color.Black;
                        backgroundColor = Color.White;
                        lightColor = Color.DarkGray;
                        darkColor = Color.DarkGray;
                        dimColor = Color.LightGray;
                        highlightColor = Color.Gray;
                        microBorders.textColor = Color.Gray;
                        worldWater.fillColor = Color.Black;
                        worldNoWater.fillColor = Color.Empty;

                        worldNoWater.fillColor = Color.White;
                        worldNoWater.pen = new PenInfo(Color.Black, onePixel);

                        riftOpacity = Math.Min(riftOpacity, 0.70f);

                        showWorldDetailColors = false;

                        break;
                    }
                case Style.Print:
                    {
                        deepBackgroundOpacity = 0f;

                        foregroundColor = Color.Black;
                        backgroundColor = Color.White;
                        lightColor = Color.DarkGray;
                        darkColor = Color.DarkGray;
                        dimColor = Color.LightGray;
                        microRoutes.pen.color = Color.Gray;

                        microBorders.textColor = Color.Brown;

                        amberZone.pen.color = Color.Gold;
                        worldNoWater.fillColor = Color.White;
                        worldNoWater.pen = new PenInfo(Color.Black, onePixel);

                        riftOpacity = Math.Min(riftOpacity, 0.70f);

                        break;
                    }
                case Style.Candy:
                    {
                        useWorldImages = true;
                        pseudoRandomStars.visible = false;

                        useBackgroundImage = deepBackgroundOpacity < 1.0f;
                        useGalaxyImage = deepBackgroundOpacity > 0.0f;

                        microBorderStyle = MicroBorderStyle.Curve;

                        sectorGrid.visible = sectorGrid.visible && (scale >= 4 && scale < 32);
                        subsectorGrid.visible = subsectorGrid.visible && (scale >= 32);
                        parsecGrid.visible = false;

                        subsectorGrid.pen.width = 0.03f * (64.0f / (float)scale);
                        subsectorGrid.pen.DashPattern = new double[] { 10.0, 8.0 };

                        sectorGrid.pen.width = 0.03f * (64.0f / (float)scale);
                        sectorGrid.pen.DashPattern = new double[] { 10.0, 8.0 };

                        worlds.textBackgroundStyle = TextBackgroundStyle.Shadow;

                        worldDetails = worldDetails
                            & ~WorldDetails.Starport & ~WorldDetails.Allegiance & ~WorldDetails.Bases & ~WorldDetails.Hex;

                        if (scale < CandyMinWorldNameScale)
                            worldDetails = worldDetails & ~WorldDetails.KeyNames & ~WorldDetails.AllNames;
                        if (scale < CandyMinUwpScale)
                            worldDetails = worldDetails & ~WorldDetails.Uwp;

                        amberZone.pen.color = Color.Goldenrod;

                        sectorName.textStyle.Rotation = 0;
                        sectorName.textStyle.Translation = new PointF(0, -0.25f);
                        sectorName.textStyle.Scale = new SizeF(0.5f, 0.25f);
                        sectorName.textStyle.Uppercase = true;

                        subsectorNames.textStyle.Rotation = 0;
                        subsectorNames.textStyle.Translation = new PointF(0, -0.25f);
                        subsectorNames.textStyle.Scale = new SizeF(0.3f, 0.15f); // Expand
                        subsectorNames.textStyle.Uppercase = true;

                        microBorders.textStyle.Rotation = 0;
                        microBorders.textStyle.Translation = new PointF(0, 0.25f);
                        microBorders.textStyle.Scale = new SizeF(1.0f, 0.5f); // Expand
                        microBorders.textStyle.Uppercase = true;

                        microBorders.pen.color = Color.FromArgb(128, Color.Red);

                        worlds.textStyle.Rotation = 0;
                        worlds.textStyle.Scale = new SizeF(1f, 0.5f); // Expand
                        worlds.textStyle.Translation = new PointF(0, 0);
                        worlds.textStyle.Uppercase = true;

                        if (scale > CandyMaxWorldRelativeScale)
                        {
                            hexContentScale = CandyMaxWorldRelativeScale / (float)scale;
                        }

                        break;
                    }
            }

            sectorName.textColor = scale < 16 ? foregroundColor :
                scale < 48 ? darkColor : dimColor;
            subsectorNames.textColor = scale < 16 ? foregroundColor :
                scale < 48 ? darkColor : dimColor;

            // Cap pen widths when zooming in
            float penScale = (scale <= 64) ? 1f : (64f / (float)scale);

            float borderPenWidth =
                (scale < MicroBorderMinScale) ? 1 : // When rendering vector borders
                (scale < ParsecMinScale) ? 1 :      // When not rendering "hexes"
                0.16f * penScale; // ... but cut in half by clipping

            float routePenWidth =
                scale <= 16 ? 0.2f :
                0.08f * penScale;

            microBorders.pen.width = borderPenWidth;
            macroBorders.pen.width = borderPenWidth;
            microRoutes.pen.width = routePenWidth;

            amberZone.pen.width = redZone.pen.width = blueZone.pen.width = 0.05f * penScale;

            macroRoutes.pen.width = borderPenWidth;
            macroRoutes.pen.DashStyle = XDashStyle.Dash;

            if (style == Style.Candy)
            {
                subsectorNames.textColor = sectorName.textColor = Color.FromArgb(128, Color.Goldenrod);

                amberZone.pen.width = redZone.pen.width = blueZone.pen.width = 0.035f;

                microRoutes.pen.width = scale < CandyMaxRouteRelativeScale ? routePenWidth : routePenWidth / 2;
                macroBorders.pen.width = scale < CandyMaxBorderRelativeScale ? borderPenWidth : borderPenWidth / 4;
                microBorders.pen.width = scale < CandyMaxBorderRelativeScale ? borderPenWidth : borderPenWidth / 4;
            }

            preferredMimeType = (style == Style.Candy)
                ? System.Net.Mime.MediaTypeNames.Image.Jpeg
                : Util.MediaTypeName_Image_Png;

            pseudoRandomStars.fillColor = foregroundColor;

            macroNames.textColor = foregroundColor;
            macroNames.textHighlightColor = highlightColor;

            macroRoutes.textColor = foregroundColor;
            macroRoutes.textHighlightColor = highlightColor;

            worlds.textColor = foregroundColor;
            worlds.textHighlightColor = highlightColor;

            hexNumber.textColor = lightColor;
            imageBorderColor = lightColor;
        }