Beispiel #1
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 #2
0
        /// <summary>
        /// Sort styles by the minimum index of their rules.
        /// This sorts a slice of the styles, so it returns a sorted
        /// array but does not change the input.
        /// </summary>
        /// <param name="styles"></param>
        /// <param name="env"></param>
        private static void SortStyles(List <CartoStyle> styles, Env env)
        {
            if (styles.Count == 0)
            {
                return;
            }

            for (var i = 0; i < styles.Count; i++)
            {
                CartoStyle style = styles[i];
                style.Index = int.MaxValue;

                for (int b = 0; b < style.Count; b++)
                {
                    NodeList <CartoRule> rules = style[b].Rules;
                    for (var r = 0; r < rules.Count; r++)
                    {
                        CartoRule rule = rules[r];
                        if (rule.Index < style.Index)
                        {
                            style.Index = rule.Index;
                        }
                    }
                }
            }

            styles.Sort(delegate(CartoStyle a, CartoStyle b) { return(a.Index.CompareTo(b.Index)); });
        }
        public static List <CartoDefinition> Flatten(this Ruleset ruleset, List <CartoDefinition> result, NodeList <CartoSelector> parents, Env env, Logging.Logger logger)
        {
            NodeList <CartoSelector> selectors       = GetCartoSelectors(ruleset);
            NodeList <CartoSelector> selectorsResult = new NodeList <CartoSelector>();

            if (selectors.Count == 0)
            {
                env.Frames.Concat(ruleset.Rules);
            }

            // evaluate zoom variables on this object.
            EvaluateZooms(selectors, env);

            for (int i = 0; i < selectors.Count; i++)
            {
                CartoSelector child = selectors[i];
                if (child.Filters == null)
                {
                    // TODO: is this internal inconsistency?
                    // This is an invalid filterset.

                    continue;
                }

                if (parents.Count > 0)
                {
                    foreach (CartoSelector parent in parents)
                    {
                        object mergedFilters = parent.Filters.CloneWith(child.Filters, env);                        //new CartoFilterSet(child.Filters);

                        if (mergedFilters == null)
                        {
                            // Filters could be added, but they didn't change the
                            // filters. This means that we only have to clone when
                            // the zoom levels or the attachment is different too.

                            if (parent.Zoom == (parent.Zoom & child.Zoom) && parent.Attachment == child.Attachment && parent.ElementsEqual(child))
                            {
                                selectorsResult.Add(parent);
                                continue;
                            }
                            else
                            {
                                mergedFilters = parent.Filters;
                            }
                        }
                        else if (mergedFilters is bool && !(Convert.ToBoolean(mergedFilters)))
                        {
                            // The merged filters are invalid, that means we don't
                            // have to clone.

                            continue;
                        }

                        CartoSelector clone = new CartoSelector(child);
                        clone.Filters = (CartoFilterSet)mergedFilters;
                        clone.Zoom    = parent.Zoom & child.Zoom;
                        clone.Elements.Clear();
                        clone.Elements.AddRange(parent.Elements.Concat(child.Elements));

                        if (parent.Attachment != null && child.Attachment != null)
                        {
                            clone.Attachment = parent.Attachment + '/' + child.Attachment;
                        }
                        else
                        {
                            clone.Attachment = child.Attachment ?? parent.Attachment;
                        }

                        clone.Conditions = parent.Conditions + child.Conditions;
                        clone.Index      = child.Index;
                        selectorsResult.Add(clone);
                    }
                }
                else
                {
                    selectorsResult.Add(child);
                }
            }

            NodeList <CartoRule> rules = new NodeList <CartoRule>();

            foreach (dotless.Core.Parser.Infrastructure.Nodes.Node rule in ruleset.Rules)
            {
                // Recursively flatten any nested rulesets
                if (rule is Ruleset)
                {
                    List <CartoDefinition> defs = Flatten(rule as Ruleset, result, selectorsResult, env, logger);
                }
                else if (rule is CartoRule)
                {
                    rules.Add(rule as CartoRule);
                }
                else if (rule as CartoInvalidElement)
                {
                    CartoInvalidElement cie = rule as CartoInvalidElement;
                    env.Logger.Log(dotless.Core.Loggers.LogLevel.Error, "Rule");
                    Logging.LogFactory.WriteLogEntry(logger, new ParsingException(cie.Value, cie.Location.FileName, Zone.GetLineNumber(cie.Location)));
                }
            }

            int index = rules.Count > 0 ? rules[0].Index : -1;

            for (int i = 0; i < selectorsResult.Count; i++)
            {
                // For specificity sort, use the position of the first rule to allow
                // defining attachments that are under current element as a descendant
                // selector.

                CartoSelector selector = selectorsResult[i];
                if (index >= 0)
                {
                    selector.Index = index;
                }

                // make a copy of the rules array, since the next iteration will change zooms
                CartoRule[] arrRules = new CartoRule[rules.Count];
                for (int j = 0; j < arrRules.Length; j++)
                {
                    arrRules[j] = (CartoRule)rules[j].Clone();
                }

                result.Add(new CartoDefinition(selector, arrRules));
            }

            return(result);
        }
Beispiel #4
0
        private static void CreateSymbolizers(Rule rule, Dictionary <string, Dictionary <string, CartoRule> > symbolizers, Env env, ICartoTranslator cartoTranslator)
        {
            // Sort symbolizers by the index of their first property definition
            List <KeyValuePair <string, int> > symOrder = new List <KeyValuePair <string, int> >();
            List <int> indexes = new List <int>();

            foreach (string key in symbolizers.Keys)
            {
                int minIdx = int.MaxValue;

                var props = symbolizers[key];
                foreach (var prop in props)
                {
                    int index = props[prop.Key].Index;
                    if (index < minIdx)
                    {
                        minIdx = index;
                    }
                }

                symOrder.Add(new KeyValuePair <string, int>(key, minIdx));
            }

            // Get a simple list of the symbolizers, in order
            symOrder.Sort(delegate(KeyValuePair <string, int> a, KeyValuePair <string, int> b) { return(a.Value.CompareTo(b.Value)); });

            foreach (KeyValuePair <string, int> kv in symOrder)
            {
                var attributes = symbolizers[kv.Key];
                var symbolizer = kv.Key.Split('/')[1];

                // Skip the magical * symbolizer which is used for universal properties
                // which are bubbled up to Style elements intead of Symbolizer elements.
                if (symbolizer == "*")
                {
                    continue;
                }

                // Check if we have all required properties

                string[] properties = attributes.Keys.ToArray();
                string[] values     = new string[properties.Length];

                string missingProperty = null;
                bool   succ            = cartoTranslator.HasRequiredProperties(symbolizer, properties, ref missingProperty);

                if (!succ)
                {
                    NodeLocation loc = attributes[missingProperty].Location;
                    throw new Exception(string.Format("A required property '{0}' is missing. Location: Index = {1} ; Source = {2}", missingProperty, loc.Index, loc.Source));
                }

                int i = 0;
                foreach (string propName in attributes.Keys)
                {
                    CartoRule cartoRule = attributes[propName];
                    values[i] = cartoRule.Value.GetValueAsString(env);
                    i++;
                }

                Symbolizer sym = cartoTranslator.ToSymbolizer(symbolizer, properties, values);
                if (sym != null && sym.Enabled)
                {
                    rule.Symbolizers.Add(sym);
                }
            }
        }
Beispiel #5
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 #6
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);
        }