/// <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; }
/// <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; }