Пример #1
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)); });
        }
Пример #2
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);
        }
Пример #3
0
        public static Map ReadFromFile(string fileContent, string fileName)
        {
            string path = Path.GetDirectoryName(fileName);

            CartoProject cartoProject = null;

            switch (Path.GetExtension(fileName).ToLower())
            {
            case ".mml":
                cartoProject = JsonConvert.DeserializeObject <CartoProject>(fileContent);

                if (cartoProject.Interactivity != null)
                {
                    try
                    {
                        Dictionary <string, object> dict = JsonConvert.DeserializeObject <Dictionary <string, object> >(cartoProject.Interactivity.ToString());
                        cartoProject.Interactivity = dict;
                    }
                    catch
                    { }

                    try
                    {
                        bool enabled = JsonConvert.DeserializeObject <bool>(cartoProject.Interactivity.ToString());
                        cartoProject.Interactivity = enabled;
                    }
                    catch
                    { }
                }
                break;

            case ".yaml":
                using (StringReader input = new StringReader(fileContent))
                {
                    Deserializer deserializer = new Deserializer(namingConvention: new CamelCaseNamingConvention(), ignoreUnmatched: true);
                    var          parser       = new MergingParser(new YamlDotNet.Core.Parser(input));
                    cartoProject = deserializer.Deserialize <CartoProject>(new EventReader(parser));
                }
                break;

            default:
                throw new Exception("Unknown extension of the CartoCSS project.");
            }

            Map map = null;

            if (cartoProject.Stylesheet != null && cartoProject.Stylesheet.Length > 0 && cartoProject.Layers.Length > 0)
            {
                ICartoTranslator cartoTranslator = CartoGeneratorConverterFactory.CreateTranslator(cartoProject.Generator);

                CartoParser parser = new CartoParser();
                parser.NodeProvider = new CartoNodeProvider();
                Env                    env         = new Env();
                List <Ruleset>         ruleSets    = new List <Ruleset>();
                List <CartoDefinition> definitions = new List <CartoDefinition>();

                foreach (string styleName in cartoProject.Stylesheet)
                {
                    string styleFileName = Path.Combine(path, styleName);

                    try
                    {
                        Ruleset ruleSet = parser.Parse(File.ReadAllText(styleFileName), styleFileName, env);

                        ruleSets.Add(ruleSet);

                        // Get an array of Ruleset objects, flattened
                        // and sorted according to specificitySort
                        var defs = new List <CartoDefinition>();
                        defs = ruleSet.Flatten(defs, null, env);
                        defs.Sort(new SpecificitySorter());

                        definitions.AddRange(defs);

                        env.Frames.Push(ruleSet);
                    }
                    catch (Exception ex)
                    {
                        Exception ex2 = new IOException(string.Format("An error occured during parsing of the style '{0}'.", styleFileName) + ex.Message);
                        LogFactory.WriteLogEntry(Logger.Default, ex2);
                        throw ex2;
                    }
                }

                string interactivityLayer = null;
                if (cartoProject.GetInteractivity() != null && cartoProject.GetInteractivity().ContainsKey("layer"))
                {
                    interactivityLayer = cartoProject.GetInteractivity()["layer"].ToString();
                }

                map = CreateMap(cartoProject, definitions, env, cartoTranslator);

                foreach (CartoLayer cartoLayer in cartoProject.Layers)
                {
                    CartoDatasource datasource  = cartoLayer.Datasource;
                    StyledLayer     styledLayer = CreateStyledLayer(cartoLayer, map, cartoTranslator);

                    try
                    {
                        string[] classes = (cartoLayer.Class.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
                        Dictionary <string, bool> classIndex = new Dictionary <string, bool>(classes.Length);
                        for (int i = 0; i < classes.Length; i++)
                        {
                            classIndex[classes[i]] = true;
                        }

                        var matching = definitions.FindAll(delegate(CartoDefinition def) { return(def.AppliesTo(cartoLayer.Name, classIndex)); });

                        if (matching.Count > 0)
                        {
                            List <CartoStyle> rules = InheritDefinitions(matching, env);

                            if (rules.Count > 0)
                            {
                                SortStyles(rules, env);

                                for (int k = 0; k < rules.Count; k++)
                                {
                                    CartoStyle cartoStyle = rules[k];
                                    cartoStyle.Fold(env);
                                    string           styleName = cartoLayer.Name + (cartoStyle.Attachment != "__default__" ? "-" + cartoStyle.Attachment : "");
                                    FeatureTypeStyle style     = CreateStyle(styleName, cartoStyle, env, cartoTranslator);

                                    if (style.Rules.Count > 0)
                                    {
                                        styledLayer.Styles.Add(style);
                                    }
                                }

                                cartoTranslator.ProcessStyles(styledLayer.Styles);
                            }

                            if (!string.IsNullOrEmpty(interactivityLayer) && interactivityLayer.Equals(styledLayer.Name))
                            {
                                styledLayer.Enabled = false;
                            }

                            map.AddLayer(styledLayer);
                        }
                    }
                    catch (Exception ex)
                    {
                        Exception ex2 = new IOException(string.Format("Unable to create data source provider with type '{0}' for the layer '{1}'.", datasource.Type, cartoLayer.Name) + ex.Message);
                        LogFactory.WriteLogEntry(Logger.Default, ex2);
                    }
                }
            }

            return(map);
        }
Пример #4
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);
        }