Beispiel #1
0
        /// <summary>
        /// Apply inherited styles from their ancestors to them.
        /// </summary>
        /// <param name="definitions"></param>
        /// <param name="env"></param>
        /// <returns>an array of arrays is returned, in which each array refers to a specific attachment</returns>
        private static List <CartoStyle> InheritDefinitions(List <CartoDefinition> definitions, Env env)
        {
            // definitions are ordered by specificity,
            // high (index 0) to low
            Dictionary <string, CartoStyle> byAttachment = new Dictionary <string, CartoStyle>();
            Dictionary <string, SortedDictionary <string, CartoDefinition> > byFilter = new Dictionary <string, SortedDictionary <string, CartoDefinition> >();
            List <CartoStyle>      result = new List <CartoStyle>();
            List <CartoDefinition> current;
            string attachment;

            // Evaluate the filters specified by each definition with the given
            // environment to correctly resolve variable references
            definitions.ForEach(delegate(CartoDefinition def) {
                def.Filters.Evaluate(env);
            });

            current = new List <CartoDefinition>();

            for (int i = 0; i < definitions.Count; i++)
            {
                CartoDefinition defI = definitions[i];
                attachment = defI.Attachment;

                current.Clear();
                current.Add(defI);

                if (!byAttachment.ContainsKey(attachment))
                {
                    CartoStyle style = new CartoStyle();
                    style.Attachment = attachment;

                    byAttachment.Add(attachment, style);
                    byAttachment[attachment].Attachment = attachment;
                    byFilter[attachment] = new SortedDictionary <string, CartoDefinition>();

                    result.Add(byAttachment[attachment]);
                }

                // Iterate over all subsequent rules.
                for (var j = i + 1; j < definitions.Count; j++)
                {
                    CartoDefinition defJ = definitions[j];
                    if (defJ.Attachment == attachment)
                    {
                        // Only inherit rules from the same attachment.
                        current = AddRules(current, defJ, byFilter[attachment], env);
                    }
                }

                for (var k = 0; k < current.Count; k++)
                {
                    byFilter[attachment][current[k].Filters.ToString()] = current[k];
                    byAttachment[attachment].Add(current[k]);
                }
            }

            return(result);
        }
Beispiel #2
0
        private static List <CartoDefinition> AddRules(List <CartoDefinition> current, CartoDefinition definition, SortedDictionary <string, CartoDefinition> byFilter, Env env)
        {
            var             newFilters = definition.Filters;
            var             newRules   = definition.Rules;
            object          updatedFilters;
            CartoDefinition clone, previous;

            // The current definition might have been split up into
            // multiple definitions already.
            for (var k = 0; k < current.Count; k++)
            {
                updatedFilters = current[k].Filters.CloneWith(newFilters, env);
                if (updatedFilters is CartoFilterSet)
                {
                    string filtersString = (updatedFilters as CartoFilterSet).ToString();

                    if (!byFilter.TryGetValue(filtersString, out previous))
                    {
                        previous = null;
                    }

                    if (previous != null)
                    {
                        // There's already a definition with those exact
                        // filters. Add the current definitions' rules
                        // and stop processing it as the existing rule
                        // has already gone down the inheritance chain.
                        previous.AddRules(newRules);
                    }
                    else
                    {
                        clone = (CartoDefinition)current[k].Clone((CartoFilterSet)updatedFilters, env);
                        // Make sure that we're only maintaining the clone
                        // when we did actually add rules. If not, there's
                        // no need to keep the clone around.
                        if (clone.AddRules(newRules) > 0)
                        {
                            // We inserted an element before this one, so we need
                            // to make sure that in the next loop iteration, we're
                            // not performing the same task for this element again,
                            // hence the k++.
                            byFilter.Add(filtersString, clone);
                            current.Insert(k, clone);
                            k++;
                        }
                    }
                }
                else if (updatedFilters == null)
                {
                    // if updatedFilters is null, then adding the filters doesn't
                    // invalidate or split the selector, so we addRules to the
                    // combined selector

                    // Filters can be added, but they don't change the
                    // filters. This means we don't have to split the
                    // definition.
                    //
                    // this is cloned here because of shared classes, see
                    // sharedclass.mss
                    current[k] = (CartoDefinition)current[k].Clone(env);
                    current[k].AddRules(newRules);
                }
                // if updatedFeatures is false, then the filters split the rule,
                // so they aren't the same inheritance chain
            }

            return(current);
        }
Beispiel #3
0
        /// <summary>
        /// Creates rules
        /// </summary>
        /// <param name="style"></param>
        /// <param name="def"></param>
        /// <param name="env"></param>
        /// <param name="existingFilters"></param>
        /// <param name="cartoTranslator"></param>
        private static void CreateRules(FeatureTypeStyle style, CartoDefinition def, Env env, Dictionary <string, int> existingFilters, ICartoTranslator cartoTranslator)
        {
            string filter = def.Filters.ToString();

            if (!(existingFilters.ContainsKey(filter)))
            {
                existingFilters[filter] = 0x7FFFFF;
            }

            int        available = 0x7FFFFF;
            ZoomStruct zooms     = new ZoomStruct();

            zooms.Available = available;

            NodeList <CartoRule> rules = def.Rules;

            for (int i = 0; i < rules.Count; i++)
            {
                CartoRule cartoRule = rules[i];
                zooms.Rule = cartoRule.Zoom;

                if ((existingFilters[filter] & zooms.Rule) == 0)
                {
                    continue;
                }

                while (((zooms.Current = zooms.Rule) & available) != 0)
                {
                    Dictionary <string, Dictionary <string, CartoRule> > symbolizers = CollectSymbolizers(def, zooms, i, env, cartoTranslator);

                    if (symbolizers != null && symbolizers.Count > 0)
                    {
                        if ((existingFilters[filter] & zooms.Current) == 0)
                        {
                            continue;
                        }

                        int zoom = existingFilters[filter] & zooms.Current;
                        int startZoom = -1, endZoom = 0;
                        for (int zi = 0; zi <= 22; zi++)
                        {
                            if ((zoom & (1 << zi)) != 0)
                            {
                                if (startZoom == -1)
                                {
                                    startZoom = zi;
                                }
                                endZoom = zi;
                            }
                        }

                        Rule rule = new Rule();
                        rule.Filter = ConvertUtility.ToFilter(def.Filters, cartoTranslator);
                        rule.Name   = cartoRule.Instance;

                        if (startZoom > 0)
                        {
                            rule.MaxScale = ConvertUtility.ToScaleDenominator(startZoom);
                        }
                        if (endZoom > 0)
                        {
                            rule.MinScale = ConvertUtility.ToScaleDenominator(endZoom + 1);
                        }

                        CreateSymbolizers(rule, symbolizers, env, cartoTranslator);

                        existingFilters[filter] &= ~zooms.Current;

                        // Check whether the rule has at least one visible symbolizer
                        if (rule.Symbolizers.Count > 0 && rule.Symbolizers.Any(s => s.Enabled == true))
                        {
                            style.Rules.Add(rule);
                        }
                    }
                }
            }

            //style.Rules.Sort(new RuleComparer());
        }
Beispiel #4
0
        private static Dictionary <string, Dictionary <string, CartoRule> > CollectSymbolizers(CartoDefinition def, ZoomStruct zooms, int i, Env env, ICartoTranslator cartoTranslator)
        {
            Dictionary <string, Dictionary <string, CartoRule> > symbolizers = new Dictionary <string, Dictionary <string, CartoRule> >();

            NodeList <CartoRule> rules = def.Rules;

            for (int j = i; j < rules.Count; j++)
            {
                CartoRule child   = rules[j];
                string    symName = cartoTranslator.GetSymbolizerName(child.Name);

                string key = child.Instance + "/" + symName;
                if ((zooms.Current & child.Zoom) != 0 &&
                    (!(symbolizers.ContainsKey(key)) || (symbolizers[key] != null && !(symbolizers[key].ContainsKey(child.Name)))))
                {
                    zooms.Current &= child.Zoom;
                    if (!(symbolizers.ContainsKey(key)))
                    {
                        symbolizers[key] = new Dictionary <string, CartoRule>();
                    }

                    symbolizers[key][child.Name] = child;
                }
            }

            if (symbolizers.Count > 0)
            {
                zooms.Rule &= (zooms.Available &= ~zooms.Current);

                return(symbolizers);
            }

            return(null);
        }
Beispiel #5
0
        /// <summary>
        /// Creates <see cref="FeatureTypeStyle"/> object
        /// </summary>
        /// <param name="styleName"></param>
        /// <param name="cartoStyle"></param>
        /// <param name="env"></param>
        /// <param name="cartoTranslator"></param>
        /// <returns></returns>
        private static FeatureTypeStyle CreateStyle(string styleName, CartoStyle cartoStyle, Env env, ICartoTranslator cartoTranslator)
        {
            FeatureTypeStyle style = new FeatureTypeStyle(styleName);

            style.ProcessFeatureOnce = true;

            List <CartoDefinition>   definitions        = cartoStyle.Definitions;
            Dictionary <string, int> existingFilters    = null;
            List <string>            imageFilters       = new List <string>();
            List <string>            imageFiltersBuffer = new List <string>();

            int k = 0;

            for (int i = 0; i < definitions.Count; i++)
            {
                CartoDefinition      def   = definitions[i];
                NodeList <CartoRule> rules = def.Rules;
                for (int j = 0; j < rules.Count; j++)
                {
                    CartoRule cartoRule = rules[j];
                    string    ruleName  = cartoRule.Name;
                    if (ruleName == "image-filters")
                    {
                        string filter = cartoRule.Value.ToString();
                        if (!imageFilters.Contains(filter))
                        {
                            style.ImageFiltersOptions.Filters.Add(cartoTranslator.ToImageFilter(filter));
                            style.ImageFiltersOptions.Enabled = true;
                            imageFilters.Add(filter);
                        }
                        k++;
                    }
                    else if (ruleName == "image-filters-inflate")
                    {
                        bool inflate = Convert.ToBoolean(cartoRule.Value.ToString());

                        if (inflate)
                        {
                            style.ImageFiltersOptions.Enabled = true;
                        }
                        k++;
                    }
                    else if (ruleName == "direct-image-filters")
                    {
                        string filter = cartoRule.Value.ToString();
                        if (!imageFiltersBuffer.Contains(filter))
                        {
                            style.ImageFiltersOptions.BufferFilters.Add(cartoTranslator.ToImageFilter(filter));
                            style.ImageFiltersOptions.Enabled = true;
                            imageFiltersBuffer.Add(filter);
                        }
                        k++;
                    }
                    else if (ruleName == "comp-op")
                    {
                        style.BlendingOptions.CompositingMode = cartoTranslator.ToCompositingMode(cartoRule.Value.Evaluate(env).ToString());
                        k++;
                    }
                    else if (ruleName == "opacity")
                    {
                        style.BlendingOptions.Opacity = (float)(cartoRule.Value.Evaluate(env) as Number).Value;
                        k++;
                    }
                    if (ruleName == "filter-mode")
                    {
                        string filterMode = cartoRule.Value.Evaluate(env).ToCSS(env);
                        if (string.Equals(filterMode, "all"))
                        {
                            style.ProcessFeatureOnce = false;
                        }
                        else if (string.Equals(filterMode, "first"))
                        {
                            style.ProcessFeatureOnce = true;
                        }

                        k++;
                    }
                }

                if (k < rules.Count)
                {
                    if (existingFilters == null)
                    {
                        existingFilters = new Dictionary <string, int>();
                    }

                    CreateRules(style, def, env, existingFilters, cartoTranslator);
                }
            }

            return(style);
        }