コード例 #1
0
        /// <summary>
        /// Write out the image associated with the symbol.
        /// </summary>
        /// <param name="ms">
        /// The symbol for which to write out the image.
        /// </param>
        /// <param name="rootName">
        /// The name associated with the symbol.
        /// </param>
        private void WriteImage(MilSymbol ms, string rootName)
        {
            const double Scale = 0.333333;

            var ct = new CompositeTransform();

            ct.ScaleX          = ct.ScaleY = Scale;
            ct.TranslateX      = -ms.Bounds.Left * Scale;
            ct.TranslateY      = -ms.Bounds.Top * Scale;
            ms.RenderTransform = ct;
            target.Width       = Scale * ms.Bounds.Width;
            target.Height      = Scale * ms.Bounds.Height;
            var path = new System.Windows.Shapes.Path
            {
                Fill            = new SolidColorBrush(Colors.White),
                Stroke          = new SolidColorBrush(Colors.White),
                StrokeThickness = 3.0,
                Data            = new RectangleGeometry
                {
                    Rect = new Rect(0, 0, target.Width - 1, target.Height - 1)
                }
            };

            target.Children.Add(path);
            target.Children.Add(ms);
#if DO_WRITES
            this.SaveImage(rootName);
#endif
            target.Children.Clear();
        }
コード例 #2
0
        /// <summary>
        /// Process the given appendix.
        /// </summary>
        /// <param name="append">
        /// The name of the appendix.
        /// </param>
        /// <param name="framed">
        /// Whether or not the symbols are framed.
        /// </param>
        private void ProcessSymbolCollection(string append, bool framed)
        {
            const double Scale = 1.0;

            // Since some appendices cross reference symbols,
            // in other appendices, we'll check to make sure
            // we haven't already drawn a particular symbol code.
            IList <string> symList = new List <string>();

            var affiliations = new[] { "U", "F", "N", "H" };
            var keys         = MilAppendix.Keys(append);

            foreach (var ap in keys)
            {
                MilSymbol ms;
                var       sc = ap;
                if (symList.Contains(sc))
                {
                    continue;
                }

                symList.Add(sc);

                // There is no affiliation for weather
                var schemeKey = CodingScheme.GetCode(sc);
                if (schemeKey == CodingScheme.Weather)
                {
                    ms = new MilSymbol(sc, Scale, "X=67.8");
                    this.ProcessSymbol(ms, sc);
                    continue;
                }

                if (schemeKey == CodingScheme.TacticalGraphics)
                {
                    sc = sc.Substring(0, 1) + "H" + sc.Substring(2, 1) + "A" + sc.Substring(4);
                    ms = new MilSymbol(sc, Scale, "H=HH;H1=H1;W=W;W1=W1;T=TT;N=N;X=XX;V=VV;C=CC;Y=YY;Q=-60.0");
                    this.ProcessSymbol(ms, sc);
                    continue;
                }

                if (!framed)
                {
                    sc = sc.Substring(0, 2) + "X" + sc.Substring(3);
                }

                foreach (var c in affiliations)
                {
                    sc = sc[0] + c + sc[2] + "P" + sc.Substring(4, 10) + "E";

                    ms = new MilSymbol(sc, Scale, null, null);
                    this.ProcessSymbol(ms, sc);
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Generates the CXML for the symbol.
        /// </summary>
        /// <param name="ms">
        /// The symbol for which to generate the CXML.
        /// </param>
        /// <param name="name">
        /// The name to associate with the symbol.
        /// </param>
        private void ProcessSymbol(MilSymbol ms, string name)
        {
            if (ms.Empty)
            {
                return;
            }

            var rootName = name.Substring(0, 10);

            this.WriteCxml(ms, rootName);
            this.WriteImage(ms, rootName);
        }
コード例 #4
0
        /// <summary>
        /// Plots a symbol to the canvas.
        /// </summary>
        /// <param name="cv">The canvas.</param>
        /// <param name="ms">The military symbol.</param>
        /// <param name="x">The x location on the canvas.</param>
        /// <param name="y">The y location on the canvas.</param>
        private static void DrawSymbol(Panel cv, MilSymbol ms, double x, double y)
        {
            if (!ms.Empty)
            {
                ms.SetValue(Canvas.TopProperty, y);
                ms.SetValue(Canvas.LeftProperty, x);

                // Not necessarily a good idea, in general, to pre-generate a bunch of tooltips
                ToolTipService.SetToolTip(ms, ms.SymbolCode + "\n" + GenerateTooltip(ms.SymbolCode));
                cv.Children.Add(ms);
            }
        }
コード例 #5
0
        public void MilHatsTest()
        {
            var ms      = new MilSymbol("IHGqSCC---" + "BC" + "qqq");
            var tf      = new[] { "BC", "DG", "EI", "GM" };
            var heights = new[] { -253, -293.3999, -253, -320.3999 };

            for (int i = 0; i < tf.Length; i++)
            {
                string sc = "IHGqSCC---" + tf[i] + "qqq";
                double d  = MilHats.Generate(ms, sc);
                Assert.IsTrue(Math.Abs(heights[i] - d) < 0.0001);
            }
        }
コード例 #6
0
        /// <summary>
        /// Generate the text block representing the possible echelon value
        /// </summary>
        /// <param name="ms">the symbol to which the generated rendering is attached.</param>
        /// <param name="symbolCode">the symbol code so we know which echelon to use</param>
        /// <returns>the height of the echelon text string above the symbol</returns>
        internal static double Generate(MilSymbol ms, string symbolCode)
        {
            // This is the maximum height generated by this combination of pieces
            Rect r = ms.BaseRect;

            if (r.IsEmpty)
            {
                return(0);
            }

            double top = r.Top;

            // Echelon ignored if modifier index represents Installation or Mobility
            char mi = ModifierCode.GetCode(symbolCode);

            if (mi == ModifierCode.Installation || mi == ModifierCode.Mobility || mi == ModifierCode.Towed)
            {
                return(top);
            }

            char echelon = GetCode(symbolCode);

            if (!Echelons.ContainsKey(echelon))
            {
                return(top);
            }

            var tb = new TextBlock {
                Style = SymbolData.GetStyle("EchelonLabels")
            };

            var height = (double)tb.GetValue(TextBlock.FontSizeProperty);

            tb.Text = Echelons[echelon];
            if (string.IsNullOrEmpty(tb.Text))
            {
                return(top);
            }

            // Make the text a little closer (0.90) to the symbol than it would otherwise be.
            top -= 0.90 * height;

            tb.FindTextExtent();
            tb.SetValue(Canvas.TopProperty, top); // this positions the top line just above the symbol, I think
            tb.SetValue(Canvas.LeftProperty, -tb.Width / 2);

            // Add the echelon to the symbol
            ms.AddChild("Echelon", tb);

            return(top); // return the new height so that other decorations can be properly placed
        }
コード例 #7
0
        /// <summary>
        /// A test to check out the various mobility settings and some echelon markings
        /// </summary>
        private static void PlotAllMobility()
        {
            Canvas cv = GetCanvas();

            if (cv == null)
            {
                return;
            }

            double x = Edge;
            double y = Tight;

            var affiliations            = new[] { "U", "F", "N", "H" };
            var categoryBattleDimension = new[] { "A", "G", "U", "F" };
            var mob = new[]
            {
                "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY",
                "NS", "NL",
                "H-", "HB", "AA", "BC", "CE", "DG", "EI", "FK", "GM"
            };

            foreach (string bd in categoryBattleDimension)
            {
                foreach (string ee in affiliations)
                {
                    foreach (string m in mob)
                    {
                        string sc;
                        if (bd == "F")
                        {
                            sc = "S" + ee + bd + "AN-----" + m + "AF*";
                        }
                        else
                        {
                            sc = "I" + ee + bd + "ASRU---" + m + "AF*";
                        }

                        var ms = new MilSymbol(sc, Scale, null, null);
                        DrawSymbol(cv, ms, x, y);
                        if ((x += Tight) > 11 * Tight)
                        {
                            x  = Edge;
                            y += Loose;
                        }
                    }
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Simple test showing that changing some values causes symbol to update.
        /// </summary>
        /// <param name="sender">This parameter is not used.</param>
        /// <param name="e">This parameter is also not used.</param>
        private void TimerTick(object sender, object e)
        {
            if (this.milSymbol == null)
            {
                this.milSymbol = new MilSymbol(
                    "IUGPSRU---DKCAE", labelString: "X=The default;V= label font;T=is Arial;H=World", scale: 2 * Scale)
                {
                    LabelG = "Hello"
                };
                DrawSymbol(GetCanvas(), this.milSymbol, 300, 300);
                return;
            }

            this.milSymbol.Angle += 2;
            int count = (int)(this.milSymbol.Angle % 360) / 36;

            this.milSymbol.SymbolCode  = "I" + CommonAffiliation[count % 4] + "GPSRU---DKCAE";
            this.milSymbol.LabelString = "F=" + this.milSymbol.Angle + "°";

            // Should be changing tooltip here too
            this.milSymbol.SetValue(Canvas.TopProperty, 300 + (100 * Math.Sin(this.milSymbol.Angle * Math.PI / 180.0)));
            this.milSymbol.SetValue(Canvas.LeftProperty, 300 + (100 * Math.Cos(this.milSymbol.Angle * Math.PI / 180.0)));
        }
コード例 #9
0
        /// <summary>
        /// Writes out the CXML file.
        /// </summary>
        /// <param name="ms">
        /// The symbol for which to generate the CXML.
        /// </param>
        /// <param name="rootName">
        /// The name to use for the symbol.
        /// </param>
        private void WriteCxml(MilSymbol ms, string rootName)
        {
            var symbolCode = (CodingScheme.GetCode(ms.SymbolCode) != CodingScheme.Weather) ? rootName + "*****" : ms.SymbolCode;

            var description = MilAppendix.Description(symbolCode);
            var lines       = description.Split(new[] { '\n' });
            var lineCount   = lines.Length - 1; // the last line is empty

            var sb = new StringBuilder();

            sb.AppendFormat(@"<Item Id=""{0}"" Name=""{1}"" Img=""Symbols\{1}.png"" Href="""">", this.index++, rootName);
            sb.AppendLine();
            if (lineCount > 0)
            {
                sb.AppendFormat(@" <Description>""{0}""</Description>", lines[lineCount - 1].Trim(new[] { ' ', '\n', '\r' }));
                sb.AppendLine();
            }
            else
            {
                sb.AppendFormat(@" <Description>""""</Description>");
                sb.AppendLine();
            }

            sb.AppendLine(@" <Facets>");
            sb.AppendLine(@"  <Facet Name=""Affiliation"">");
            sb.AppendFormat(@"   <String Value=""{0}"" />", StandardIdentity.GetName(symbolCode));
            sb.AppendLine();
            sb.AppendLine(@"  </Facet>");
            sb.AppendLine(@"  <Facet Name=""Battle Dimension"">");
            sb.AppendFormat(@"   <String Value=""{0}"" />", CategoryBattleDimension.GetName(symbolCode));
            sb.AppendLine();
            sb.AppendLine(@"  </Facet>");
            if (lineCount > 2)
            {
                sb.AppendLine(@"  <Facet Name=""Type"">");
                sb.AppendFormat(@"   <String Value=""{0}"" />", lines[2].Trim(new[] { ' ', '\n', '\r' }));
                sb.AppendLine();
                sb.AppendLine(@"  </Facet>");
            }

            sb.AppendLine(@"  <Facet Name=""Coding Scheme"">");
            sb.AppendFormat(@"   <String Value=""{0}"" />", CodingScheme.GetName(symbolCode));
            sb.AppendLine();
            sb.AppendLine(@"  </Facet>");
            if (lineCount - 1 > 3)
            {
                sb.AppendLine(@"  <Facet Name=""Key Phrases"">");
                for (var i = 3; i < lineCount - 1; i++)
                {
                    sb.AppendFormat(@"   <String Value=""{0}"" />", lines[i].Trim(new[] { ' ', '\n', '\r' }));
                    sb.AppendLine();
                }

                sb.AppendLine(@"  </Facet>");
            }

            sb.AppendLine(@" </Facets>");
            sb.AppendLine(@"</Item>");

#if DO_WRITES
            this.cxmlStream.Write(sb.ToString());
#endif
        }
コード例 #10
0
        /// <summary>
        /// Plots all of the core symbols that are in Appendix D.
        /// Since not all symbol codes are non-blank, there are some blanks in the output.
        /// Refer to MIL-STD 2525C for comparison.
        /// </summary>
        /// <param name="append">
        /// The appendix from which to get the symbols.
        /// </param>
        /// <param name="framed">
        /// Whether or not the symbols are framed.
        /// </param>
        private static void PlotAllSymbols(string append, bool framed)
        {
            Canvas cv = GetCanvas();

            if (cv == null)
            {
                return;
            }

            // Since some appendices cross reference symbols,
            // in other appendices, we'll check to make sure
            // we haven't already drawn a particular symbol code.
            IList <string> symList = new List <string>();

            double x = Edge;
            double y = Edge;

            var  affiliations = new[] { "U", "F", "N", "H" };
            bool first        = true;

            var keys = MilAppendix.Keys(append);

            foreach (string ap in keys)
            {
                string sc = ap;
                if (symList.Contains(sc))
                {
                    continue;
                }

                symList.Add(sc);

                // There is no affiliation for weather
                int schemeKey = CodingScheme.GetCode(sc);
                if (schemeKey == CodingScheme.Weather)
                {
                    // Check centering
                    // var ls1 = new Line { X1 = x + 5, Y1 = y + 5, X2 = x - 5, Y2 = y - 5, Stroke = new SolidColorBrush(Colors.Red), StrokeThickness = 1 };
                    // var ls2 = new Line { X1 = x - 5, Y1 = y + 5, X2 = x + 5, Y2 = y - 5, Stroke = new SolidColorBrush(Colors.Red), StrokeThickness = 1 };
                    // cv.Children.Add(ls1);
                    // cv.Children.Add(ls2);
                    var ms = new MilSymbol(sc, Scale, "X=67.8");
                    DrawSymbol(cv, ms, x, y);
                    if ((x += Tight) > 12 * Tight)
                    {
                        x  = Edge;
                        y += Tight;
                    }

                    continue;
                }

                if (schemeKey == CodingScheme.TacticalGraphics)
                {
                    // Check centering
                    // var ls1 = new Line { X1 = x + 5, Y1 = y + 5, X2 = x - 5, Y2 = y - 5, Stroke = new SolidColorBrush(Colors.Red), StrokeThickness = 1 };
                    // var ls2 = new Line { X1 = x - 5, Y1 = y + 5, X2 = x + 5, Y2 = y - 5, Stroke = new SolidColorBrush(Colors.Red), StrokeThickness = 1 };
                    // cv.Children.Add(ls1);
                    // cv.Children.Add(ls2);
                    sc = sc.Substring(0, 1) + "H" + sc.Substring(2, 1) + "A" + sc.Substring(4);
                    var ms = new MilSymbol(sc, Scale, "H=HH;H1=H1;W=W;W1=W1;T=TT;N=N;X=XX;V=VV;C=CC;Y=YY;Q=-60.0");
                    DrawSymbol(cv, ms, x, y);
                    if ((x += Tight) > 12 * Tight)
                    {
                        x  = Edge;
                        y += Tight + 25;
                    }

                    continue;
                }

                if (!framed)
                {
                    sc = sc.Substring(0, 2) + "X" + sc.Substring(3);
                }

                foreach (string c in affiliations)
                {
                    sc = sc[0] + c + sc[2] + "C" + sc.Substring(4, 10) + "E";

                    var ms = new MilSymbol(sc, Scale, null, null);
                    if (first && ms.Empty)
                    {
                        continue;
                    }

                    first = false;
                    DrawSymbol(cv, ms, x, y);

                    if ((x += Tight) > 12 * Tight)
                    {
                        x  = Edge;
                        y += Tight;
                    }
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// A test to make sure that all of the supported labels go into the right
        /// places and do the right things.
        /// </summary>
        private static void PlotAllLabels()
        {
            // Example using Run: <Run Foreground='Purple'>KK</Run>
            var labels = new[]
            {
                "C=12345;F=±", "G=GG;H=HH", "J=JJ;K=KK", "L=LL;M=MM", "N=NN;P=PP",
                "Q=30.6;T=TT", "V=VV;W=WW", "X=XX;Y=YY", "Z=ZZ;AA=ABCDEF",

                // Can't use = as separator in this string because of Foreground='Green', etc.
                "C:12345;F:±;G:Staff comments;H:H;J:J;" +
                "K:<Run Foreground='Green' FontWeight='Bold' FontStyle='Italic'>KK</Run>;" +
                "L:L;M:M;N:N;P:P;Q:30.6;" +
                "T:T;V:VvV;W:WwW;X:X;Y:Y;Z:ZzZzZ;AA:ABCDEF"
            };
            Canvas cv = GetCanvas();

            if (cv == null)
            {
                return;
            }

            var saveScheme = MilBrush.ColorScheme;

            MilBrush.ColorScheme = ColorSchemeProperty.Medium;

            double x = Tight;
            double y = Loose;

            var baseCode     = new[] { "IUAASRU---", "SUGAEVAL--", "IUUASRU---" };
            var affiliations = new[] { "U", "F", "N", "H" };

            var style = new Style(typeof(TextBlock));

            style.Setters.Add(new Setter(TextBlock.FontFamilyProperty, new FontFamily("Times New Roman")));
            style.Setters.Add(new Setter(TextBlock.FontSizeProperty, 84.0));
            style.Setters.Add(new Setter(TextBlock.FontWeightProperty, FontWeights.Bold));
            style.Setters.Add(new Setter(TextBlock.ForegroundProperty, new SolidColorBrush(Colors.Brown)));

            int count      = 0;
            var unknowns   = new[] { "U", "W", "P", "G" };
            var friendlies = new[] { "F", "A", "D", "M", "J", "K" };
            var hostiles   = new[] { "H", "S" };
            var neutrals   = new[] { "N", "L" };

            foreach (string bd in baseCode)
            {
                foreach (string ee in affiliations)
                {
                    foreach (string m in labels)
                    {
                        string af = string.Empty;
                        switch (ee)
                        {
                        case "U":
                            af = unknowns[count % 4];
                            break;

                        case "F":
                            af = friendlies[count % 6];
                            break;

                        case "H":
                            af = hostiles[count % 2];
                            break;

                        case "N":
                            af = neutrals[count % 2];
                            break;
                        }

                        count++;
                        string sc = bd.Substring(0, 1) + af + bd.Substring(2, 8) + "--" + "***";
                        var    ms = new MilSymbol(sc, Scale, m, null, null, style);
                        DrawSymbol(cv, ms, x, y);
                        if ((x += Wide) > 5 * Wide)
                        {
                            x  = Tight;
                            y += Loose;
                        }
                    }
                }

                style = null;
            }

            MilBrush.ColorScheme = saveScheme;
        }
コード例 #12
0
        /// <summary>
        /// Plot a Miscellaneous collection of symbols to extend code coverage.
        /// </summary>
        private static void PlotMiscellany()
        {
            // Create a diagonal linear gradient with four stops.
            var linBrush = new LinearGradientBrush {
                StartPoint = new Point(0, 0), EndPoint = new Point(0, 1)
            };

            linBrush.GradientStops.Add(CreateGradientStop(Color.FromArgb(255, 255, 255, 160), 0.0));
            linBrush.GradientStops.Add(CreateGradientStop(Color.FromArgb(255, 255, 160, 160), 0.4));
            linBrush.GradientStops.Add(CreateGradientStop(Color.FromArgb(255, 160, 160, 255), 0.6));
            linBrush.GradientStops.Add(CreateGradientStop(Color.FromArgb(255, 160, 255, 160), 1.0));

#if WINDOWS_UWP
            var uri = new Uri("ms-appx:///Assets/IcelandFlag64.png", UriKind.Absolute);
            var bmi = new BitmapImage(uri);
#else
            StreamResourceInfo sr = Application.GetResourceStream(
                new Uri("Resources/IcelandFlag64.png", UriKind.Relative));
            if (sr == null)
            {
                Log.WriteMessage(
                    LogLevel.Error,
                    "Cannot find the IcelandFlag64.png resource. Should be in GraphicsTest/Resources.");
                return;
            }
            var bmi = new BitmapImage();
#endif

#if SILVERLIGHT
            bmi.SetSource(sr.Stream);
#elif !WINDOWS_UWP
            bmi.BeginInit();
            bmi.StreamSource = sr.Stream;
            bmi.EndInit();
#endif
            var imageBrush = new ImageBrush {
                ImageSource = bmi, Opacity = 0.5, Stretch = Stretch.UniformToFill
            };

            Canvas cv = GetCanvas();
            if (cv == null)
            {
                return;
            }

            double x = 50;
            double y = 50;

            var affiliations = new[] { "U", "A", "N", "H" };
            foreach (string ee in affiliations)
            {
                string sc = "I" + ee + "GPSRU----F***";

                var ms = new MilSymbol(sc, Scale, null, new SolidColorBrush(Colors.Cyan), linBrush);
                DrawSymbol(cv, ms, x, y);

                MilBrush.ColorScheme = ColorSchemeProperty.Dark;
                ms = new MilSymbol(sc, Scale, null, null);
                DrawSymbol(cv, ms, x += 50, y);

                MilBrush.ColorScheme = ColorSchemeProperty.Medium;
                ms = new MilSymbol(sc, Scale, null, new SolidColorBrush(Colors.Orange));
                DrawSymbol(cv, ms, x += 50, y);

                MilBrush.ColorScheme = ColorSchemeProperty.Light;
                ms = new MilSymbol(sc, Scale, null, null);
                DrawSymbol(cv, ms, x += 50, y);

                sc = "I" + ee + "GDSRU----J***";
                ms = new MilSymbol(sc, Scale, null, null, linBrush);
                DrawSymbol(cv, ms, x += 50, y);

                sc = "I" + ee + "GXSRU----N***";
                ms = new MilSymbol(sc, Scale, null, null, linBrush);
                DrawSymbol(cv, ms, x += 50, y);

                sc = "I" + ee + "ZPSRU----D***";
                ms = new MilSymbol(sc, Scale, null, null, imageBrush);
                DrawSymbol(cv, ms, x += 50, y);

                sc = "I" + ee + "ZASRU----B**C";
                ms = new MilSymbol(sc, Scale, null, new SolidColorBrush(Colors.Green));

                // ReSharper disable RedundantAssignment
                DrawSymbol(cv, ms, x += 50, y);

                // ReSharper restore RedundantAssignment
                x  = 50;
                y += 75;
            }

            // Cloud cover
            x = 0;
            for (int i = 0; i < 10; i++)
            {
                var ms = new MilSymbol("WAS-WC----P----", Scale, "AA=" + i);
                DrawSymbol(cv, ms, x += 50, y);
            }

            y += 75;

            // Wind barbs with no speeds
            x = 0;
            for (int i = 0; i < 10; i++)
            {
                var ms = new MilSymbol("WAS-WP----P----", 2.0 * Scale, "AA=" + i + ";Q=" + (i * 36));
                DrawSymbol(cv, ms, x += 50, y);
            }

            y += 75;

            // Wind barbs with speeds
            x = 0;
            for (int i = 0; i < 10; i++)
            {
                string labels = "AA=" + i + ";Q=135;" + "Z=" + (i * 12.6);
                if (i > 5)
                {
                    labels += ";Y=S";
                }

                var ms = new MilSymbol("WAS-WP----P----", 2.0 * Scale, labels);
                DrawSymbol(cv, ms, x += 50, y);
            }

            y += 75;

            var brushes = new[] { new SolidColorBrush(Colors.Black), null, new SolidColorBrush(Colors.Magenta) };
            x = 0;
            for (int i = 0; i < 3; i++)
            {
                var newScale = (i == 0) ? Scale : -Scale;
                var ms       = new MilSymbol("WAS-WSTSD-P----", newScale, null, brushes[i], brushes[i]);
                DrawSymbol(cv, ms, x += 50, y);
                ms = new MilSymbol("WAS-WSTSS-P----", newScale, null, brushes[i], brushes[i]);
                DrawSymbol(cv, ms, x += 50, y);
                ms = new MilSymbol("WAS-WSTSH-P----", newScale, null, brushes[i], brushes[i]);
                DrawSymbol(cv, ms, x += 50, y);
            }

            var dms = new MilSymbol("WOS-HDS---P----", Scale, "X=67.8");

            // ReSharper disable RedundantAssignment
            DrawSymbol(cv, dms, x += 50, y);

            // ReSharper restore RedundantAssignment
        }
コード例 #13
0
        /// <summary>
        /// Generates a PNG-based byte array representing a MilSymbol code.
        /// </summary>
        /// <param name="symbolIdCode">
        /// The MilSymbol code.
        /// </param>
        /// <param name="scale">
        /// The scale, typically a number between 0 and 1.
        /// </param>
        /// <param name="labelString">
        /// The labels for the symbol.
        /// </param>
        /// <param name="opacity">
        /// The opacity for the symbol.
        /// </param>
        /// <param name="lineBrush">
        /// The line brush for coloring the symbol's outline.
        /// </param>
        /// <param name="fillBrush">
        /// The fill brush for coloring the symbol's background.
        /// </param>
        /// <param name="storagePath">
        /// The storage path for caching the PNG.
        /// </param>
        /// <param name="context">
        /// The request/response context.
        /// </param>
        /// <returns>
        /// A boolean indicating whether we have a bitmap.
        /// </returns>
        public static bool GetSymbolBuffer(
            string symbolIdCode,
            double scale,
            string labelString,
            double opacity,
            Brush lineBrush,
            Brush fillBrush,
            string storagePath,
            HttpListenerContext context)
        {
            if (symbolIdCode.Length < 4 || symbolIdCode.Length > 15)
            {
                return(false);
            }

            if (symbolIdCode.Length < 15)
            {
                symbolIdCode += Padding.Substring(symbolIdCode.Length);
            }

            var symbol = new MilSymbol(symbolIdCode, scale, labelString, lineBrush, fillBrush);

            if (symbol.Bounds == Rect.Empty)
            {
                symbolIdCode = symbolIdCode.Substring(0, 4) + Padding.Substring(4);
                symbol       = new MilSymbol(symbolIdCode, scale, labelString, lineBrush, fillBrush);

                if (symbol.Bounds == Rect.Empty)
                {
                    return(false);
                }
            }

            // Create a bigger pixel map if we're doing labels
            var size = (labelString.Length > 0) ? (int)(scale * 2000d) : (int)(scale * 600d);

            symbol.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
            var halfSize = size / 2;

            symbol.Arrange(new Rect(halfSize, halfSize, size, size));
            symbol.UpdateLayout();

            symbol.Opacity = opacity;

            var bitmap = new RenderTargetBitmap(size, size, 96, 96, PixelFormats.Default);

            bitmap.Render(symbol);

            var encoder = new PngBitmapEncoder();

            encoder.Frames.Add(BitmapFrame.Create(bitmap));

            // Cannot save the encoder output directly to the OutputStream - bummer
            using (var stream = new MemoryStream())
            {
                encoder.Save(stream);
                using (var file = new FileStream(storagePath, FileMode.Create, FileAccess.Write))
                {
                    stream.WriteTo(file);
                }

                stream.WriteTo(context.Response.OutputStream);
                return(true);
            }
        }