/// <summary>
        /// Return a list of Styles within Rules contained in a FeatureTypeStyle that match the filter criteria
        /// for this row
        /// </summary>
        /// <param name="row"></param>
        /// <param name="featureTypeStyle"></param>
        /// <returns></returns>
        public FeatureTypeStyle FilterFeatureTypeStyle(FeatureDataRow row, FeatureTypeStyle featureTypeStyle)
        {
            int  result                     = 0;
            bool ruleConditionMet           = false;
            bool atLeastOneRuleConditionMet = false;

            Type             type = null;
            object           a, b;
            FeatureTypeStyle filtered = new FeatureTypeStyle();

            filtered.Rules = new List <Rule>();
            Rule _ElseFilterRule = null;

            foreach (Rule thisRule in featureTypeStyle.Rules)
            {
                //Check that layer will be rendered for rule
                //TODO: implement scale
                //if (thisRule.MinScaleDenominatorSpecified && _mapScale < thisRule.MinScaleDenominator)
                //    continue;

                //if (thisRule.MaxScaleDenominatorSpecified && _mapScale >= thisRule.MaxScaleDenominator)
                //    continue;

                ruleConditionMet = false;

                if (thisRule.ElseFilterSpecified)
                {
                    _ElseFilterRule = thisRule;
                    break;
                }

                if (thisRule.FilterSpecified && thisRule.Filter.FilterExpressionSpecified)
                {
                    switch (thisRule.Filter.FilterSelection)
                    {
                    case Ogc.Common.FilterTypes.PropertyIsEqualTo:
                    {
                        PropertyIsEqualTo filter = thisRule.Filter.FilterExpression as PropertyIsEqualTo;

                        if (filter != null)
                        {
                            type = row.Table.Columns[filter.PropertyName].DataType;

                            a                = Convert.ChangeType(row[filter.PropertyName].ToString().Trim(), type);
                            b                = Convert.ChangeType(filter.Literal.Value, type);
                            result           = Comparer.Default.Compare(a, b);
                            ruleConditionMet = (result == 0);
                        }
                    }
                    break;

                    case Ogc.Common.FilterTypes.PropertyIsGreaterThan:
                    {
                        PropertyIsGreaterThan filter = thisRule.Filter.FilterExpression as PropertyIsGreaterThan;

                        if (filter != null)
                        {
                            type = row.Table.Columns[filter.PropertyName].DataType;

                            a                = Convert.ChangeType(row[filter.PropertyName].ToString().Trim(), type);
                            b                = Convert.ChangeType(filter.Literal.Value, type);
                            result           = Comparer.Default.Compare(a, b);
                            ruleConditionMet = (result > 0);
                        }
                    }
                    break;

                    case Ogc.Common.FilterTypes.PropertyIsGreaterThanOrEqualTo:
                    {
                        PropertyIsGreaterThanOrEqualTo filter = thisRule.Filter.FilterExpression as PropertyIsGreaterThanOrEqualTo;

                        if (filter != null)
                        {
                            type = row.Table.Columns[filter.PropertyName].DataType;

                            a                = Convert.ChangeType(row[filter.PropertyName].ToString().Trim(), type);
                            b                = Convert.ChangeType(filter.Literal.Value, type);
                            result           = Comparer.Default.Compare(a, b);
                            ruleConditionMet = (result >= 0);
                        }
                    }
                    break;

                    case Ogc.Common.FilterTypes.PropertyIsLessThan:
                    {
                        PropertyIsLessThan filter = thisRule.Filter.FilterExpression as PropertyIsLessThan;

                        if (filter != null)
                        {
                            type = row.Table.Columns[filter.PropertyName].DataType;

                            a                = Convert.ChangeType(row[filter.PropertyName].ToString().Trim(), type);
                            b                = Convert.ChangeType(filter.Literal.Value, type);
                            result           = Comparer.Default.Compare(a, b);
                            ruleConditionMet = (result < 0);
                        }
                    }
                    break;

                    case Ogc.Common.FilterTypes.PropertyIsLessThanOrEqualTo:
                    {
                        PropertyIsLessThanOrEqualTo filter = thisRule.Filter.FilterExpression as PropertyIsLessThanOrEqualTo;

                        if (filter != null)
                        {
                            type = row.Table.Columns[filter.PropertyName].DataType;

                            a                = Convert.ChangeType(row[filter.PropertyName].ToString().Trim(), type);
                            b                = Convert.ChangeType(filter.Literal.Value, type);
                            result           = Comparer.Default.Compare(a, b);
                            ruleConditionMet = (result <= 0);
                        }
                    }
                    break;

                    case Ogc.Common.FilterTypes.PropertyIsBetween:
                    {
                        PropertyIsBetween filter = thisRule.Filter.FilterExpression as PropertyIsBetween;

                        if (filter != null)
                        {
                            type = row.Table.Columns[filter.PropertyName].DataType;

                            a = Convert.ChangeType(row[filter.PropertyName].ToString().Trim(), type);
                            if (filter.LowerBoundarySpecified)
                            {
                                object lowerBound = Convert.ChangeType(filter.LowerBoundary.Value, type);
                                result           = Comparer.Default.Compare(a, lowerBound);
                                ruleConditionMet = (result >= 0);
                            }

                            if (filter.UpperBoundarySpecified)
                            {
                                object upperBound = Convert.ChangeType(filter.UpperBoundary.Value, type);
                                result            = Comparer.Default.Compare(a, upperBound);
                                ruleConditionMet &= (result <= 0);
                            }
                        }
                    }
                    break;

                    case Ogc.Common.FilterTypes.PropertyIsLike:
                    {
                        PropertyIsLike filter = thisRule.Filter.FilterExpression as PropertyIsLike;

                        if (filter != null)
                        {
                            type = row.Table.Columns[filter.PropertyName].DataType;
                            if (type == typeof(String))
                            {
                                string lookIn          = row[filter.PropertyName].ToString().Trim();
                                string originalLookFor = filter.Literal.Value;
                                string lookFor         = originalLookFor.Replace("%", string.Empty);
                                bool   likeResult      = false;

                                if (originalLookFor.StartsWith("%") && originalLookFor.EndsWith("%"))
                                {
                                    likeResult = lookIn.Contains(lookFor);
                                }
                                else if (originalLookFor.StartsWith("%"))
                                {
                                    likeResult = lookIn.EndsWith(lookFor);
                                }
                                else if (originalLookFor.EndsWith("%"))
                                {
                                    likeResult = lookIn.StartsWith(lookFor);
                                }

                                ruleConditionMet = likeResult;
                            }
                        }
                    }
                    break;

                    case Ogc.Common.FilterTypes.PropertyIsNotEqualTo:
                    {
                        PropertyIsNotEqualTo filter = thisRule.Filter.FilterExpression as PropertyIsNotEqualTo;

                        if (filter != null)
                        {
                            type = row.Table.Columns[filter.PropertyName].DataType;

                            a                = Convert.ChangeType(row[filter.PropertyName].ToString().Trim(), type);
                            b                = Convert.ChangeType(filter.Literal.Value, type);
                            result           = Comparer.Default.Compare(a, b);
                            ruleConditionMet = (result != 0);
                        }
                    }
                    break;

                    case Ogc.Common.FilterTypes.PropertyIsNull:
                    {
                        PropertyIsNull filter = thisRule.Filter.FilterExpression as PropertyIsNull;

                        if (filter != null)
                        {
                            ruleConditionMet = (row[filter.PropertyName] == null);
                        }
                    }
                    break;
                    }
                }
                else if (thisRule.ElseFilterSpecified == false)
                {
                    // No filter
                    ruleConditionMet = true;
                }

                if (ruleConditionMet)
                {
                    atLeastOneRuleConditionMet = true;
                    filtered.Rules.Add(thisRule);
                }
            } // foreach Rule

            // None of the Rule Conditions have been met, apply the Else Filter
            if (!atLeastOneRuleConditionMet && _ElseFilterRule != null)
            {
                atLeastOneRuleConditionMet = true;
                filtered.Rules.Add(_ElseFilterRule);
            }

            return(filtered);
        }
        private void EvaluatePolygonStyle(FeatureDataRow featureDataRow, ViewContext context, out System.Drawing.Brush brush, out System.Drawing.Pen pen)
        {
            brush = null;
            pen   = null;

            FeatureTypeStyle featureTypeStyle = this.StyleList[0].SLD.StyledLayerDescriptor.UserLayers[0].UserStyles[0].FeatureTypeStyles[0];
            FeatureTypeStyle filtered         = FilterFeatureTypeStyle(featureDataRow, featureTypeStyle);

            foreach (Rule rule in filtered.Rules)
            {
                foreach (BaseSymbolizer symbolizer in rule.Symbolizers)
                {
                    if (symbolizer.GetType().FullName == "GeospatialServices.Ogc.Wmc.PolygonSymbolizer")
                    {
                        if (((PolygonSymbolizer)symbolizer).Fill.SvgParameters.Count > 0)
                        {
                            PolygonSymbolizer polygonSymbolizer = symbolizer as PolygonSymbolizer;

                            if (polygonSymbolizer != null)
                            {
                                // Polygon Fill applies to brush
                                if (polygonSymbolizer.Fill.GraphicFillSpecified)
                                {
                                    Color c       = Color.Black;
                                    int   opacity = 255;
                                    foreach (GeospatialServices.Ogc.Wmc.SvgParameter svgParm in polygonSymbolizer.Fill.SvgParameters)
                                    {
                                        switch (svgParm.Name)
                                        {
                                        case "fill":
                                            c = System.Drawing.ColorTranslator.FromHtml(svgParm.Expression);
                                            break;

                                        case "fill-opacity":
                                            opacity = ConvertOpacityToStyle(svgParm.Expression);
                                            break;
                                        }
                                    }

                                    string     hatchStyleString = polygonSymbolizer.Fill.GraphicFill.Graphic.ExternalGraphics[0].OnlineResource.Href;
                                    HatchStyle hatchStyle       = (HatchStyle)Enum.Parse(typeof(HatchStyle), hatchStyleString, true);
                                    brush = new HatchBrush(hatchStyle, Color.FromArgb(opacity, c.R, c.G, c.B), Color.Transparent);
                                }
                                else
                                {
                                    Color c       = Color.Black;
                                    int   opacity = 255;
                                    foreach (GeospatialServices.Ogc.Wmc.SvgParameter svgParm in polygonSymbolizer.Fill.SvgParameters)
                                    {
                                        switch (svgParm.Name)
                                        {
                                        case "fill":
                                            c = System.Drawing.ColorTranslator.FromHtml(svgParm.Expression);
                                            break;

                                        case "fill-opacity":
                                            opacity = ConvertOpacityToStyle(svgParm.Expression);
                                            break;
                                        }
                                    }
                                    brush = new SolidBrush(Color.FromArgb(opacity, c.R, c.G, c.B));
                                }

                                // Polygon Stroke applies to pen
                                if (polygonSymbolizer.StrokeSpecified)
                                {
                                    Color c       = Color.Gray;
                                    int   opacity = 255;
                                    int   width   = 1;
                                    foreach (GeospatialServices.Ogc.Wmc.SvgParameter svgParm in polygonSymbolizer.Stroke.SvgParameters)
                                    {
                                        switch (svgParm.Name)
                                        {
                                        case "stroke":
                                            c = System.Drawing.ColorTranslator.FromHtml(svgParm.Expression);
                                            break;

                                        case "stroke-opacity":
                                            opacity = ConvertOpacityToStyle(svgParm.Expression);
                                            break;

                                        case "stroke-width":
                                            width = int.Parse(svgParm.Expression);
                                            break;
                                        }
                                    }
                                    pen = new Pen(Color.FromArgb(opacity, c.R, c.G, c.B), width);
                                }
                                else
                                {
                                    pen = null;
                                }
                            }
                        }
                    }
                }
            }
        }