public override Symbolizer ToSymbolizer(string symbolizer, NodePropertyValue[] properties)
    {
      if (string.IsNullOrEmpty(symbolizer))
        return null;

      if (symbolizer.IndexOf('_') >= 0)
        symbolizer = symbolizer.Split('_')[0];

      switch (symbolizer)
      {
        case "LineSymbolizer":
          return CreateLineSymbolizer(properties);
        case "LinePatternSymbolizer":
          return CreateLinePatternSymbolizer(properties);
        case "PolygonSymbolizer":
          return CreatePolygonSymbolizer(properties);
        case "TextSymbolizer":
          return CreateTextSymbolizer(properties);
        case "PointSymbolizer":
          return CreatePointSymbolizer(properties);
        case "GraphicTextSymbolizer":
          return CreateGraphicTextSymbolizer(properties);
        case "RasterSymbolizer":
          return CreateRasterSymbolizer(properties);
        case "ExtrudedPolygonSymbolizer":
          return CreateExtrudedPolygonSymbolizer(properties);
        default:
          break;
      }

      return null;
    }
        public bool IsSymbolizerPropertyValid(string symbolizer, NodePropertyValue property)
        {
            SymbolizerDescriptor symDesc = null;

            if (m_typesDict.TryGetValue(symbolizer, out symDesc))
            {
                bool bFound = false;
                foreach (string symProperty in symDesc.Properties.Keys)
                {
                    if (string.Equals(symProperty, property.Name))
                    {
                        bFound = true;
                        break;
                    }
                }

                return(bFound);
            }

            return(false);
        }
    private ExtrudedPolygonSymbolizer CreateExtrudedPolygonSymbolizer(NodePropertyValue[] properties)
    {
      ExtrudedPolygonSymbolizer symExtPoly = new ExtrudedPolygonSymbolizer();
      symExtPoly.Clip = false;

      NodePropertyValue pv = null;

      try
      {
        int nProps = properties.Length;

        for (int i = 0; i < nProps; i++)
        {
          pv = properties[i];

          switch (pv.Name)
          {
            case "building-fill":
              Color clr = ColorUtility.FromHtml(pv.Value);
              symExtPoly.FacesColor = clr;
              symExtPoly.TopColor = clr;
              break;
            case "building-fill-opacity":
              symExtPoly.FillOpacity = Convert.ToSingle(pv.Value);
              break;
            case "building-height":
              symExtPoly.HeightExpression = ToExpression(pv.Value);
              break;
          }
        }
      }
      catch (Exception ex)
      {
        ThrowParsingException(ex, pv);
      }

      return symExtPoly;
    }
    private PointSymbolizer CreatePointSymbolizer(NodePropertyValue[] properties)
    {
      PointSymbolizer symPoint = new PointSymbolizer();

      int pointType = properties[0].Name.StartsWith("point-") ? 0 : 1;
      bool isArrow = HasPropertyValue(properties, "marker-file", "shape://arrow");

      if (pointType == 1 && isArrow)
        pointType = 2;

      ExternalGraphicSymbol pointSymbol = null;
      MarkGraphicSymbol markSymbol = null;
      GlyphGraphicSymbol glyphSymbol = null;

      LabelPlacementInfo lpi = new LabelPlacementInfo();

      if (pointType == 0 || (!isArrow && HasProperty(properties ,"marker-file")))
      {
        pointSymbol = new ExternalGraphicSymbol();
        symPoint.Graphic.GraphicSymbols.Add(pointSymbol);
        lpi.Placement = "centroid";
        lpi.Symbolizer = (int)SymbolizerType.Point;
      }
      else if (pointType == 1)
      {
        markSymbol = new MarkGraphicSymbol();
        symPoint.Graphic.GraphicSymbols.Add(markSymbol);
        lpi.Symbolizer = (int)SymbolizerType.Marker;
      }
      else
      {
        glyphSymbol = new GlyphGraphicSymbol();
        symPoint.Graphic.GraphicSymbols.Add(glyphSymbol);
        lpi.Symbolizer = (int)SymbolizerType.Marker;
      }

      float width = 10F, height = 0F;
      NodePropertyValue pv = null;

      try
      {
        int nProps = properties.Length;

        for (int i = 0; i < nProps; i++)
        {
          pv = properties[i];

          if (pointType == 0)
          {
            switch (pv.Name)
            {
              case "point-file":
                pointSymbol.Path = ToPath(pv.Value);
                break;
              case "point-allow-overlap":
                symPoint.LabelBehaviour.AllowOverlap = Convert.ToBoolean(pv.Value);
                break;
              case "point-ignore-placement":
                symPoint.LabelBehaviour.CollisionDetectable = !Convert.ToBoolean(pv.Value);
                break;
              case "point-opacity":
                pointSymbol.Opacity = Convert.ToSingle(pv.Value);
                break;
              case "point-placement":
                lpi.Placement = pv.Value;
                break;
              case "point-transform":
                UnsupportedProperty(pv);
                break;
              case "point-comp-op":
                //UnsupportedProperty(pv.Name);
                AddProperty(symPoint, "comp-op", pv.Value);
                break;
            }
          }
          else
          {
            switch (pv.Name)
            {
              case "marker-file":
                if (pointSymbol != null)
                  pointSymbol.Path = ToPath(pv.Value);
                else if (glyphSymbol != null)
                {
                  if (FontUtility.IsFontInstalled("DejaVu Sans"))
                  {
                    glyphSymbol.TextStyle.Font.Name = "DejaVu Sans";
                    glyphSymbol.TextStyle.Font.Stretch = 1.2F;
                    glyphSymbol.Unicode = 8594;
                  }
                  else if (FontUtility.IsFontInstalled("Segoe UI"))
                  {
                    glyphSymbol.TextStyle.Font.Name = "Segoe UI";
                    glyphSymbol.Unicode = 2192;
                  }

                }
                break;
              case "marker-opacity":
                float value = Convert.ToSingle(pv.Value);
                if (pointSymbol != null)
                  pointSymbol.Opacity = value;
                else if (symPoint.Graphic != null)
                  symPoint.Graphic.Opacity /*markSymbol.Opacity*/ = value;

                if (value == 0.0F)
                  symPoint.Enabled = false;
                break;
              case "marker-line-color":
                Color clr = ColorUtility.FromHtml(pv.Value);
                if (markSymbol != null)
                  markSymbol.Stroke.Color = clr;
                else if (glyphSymbol != null)
                  glyphSymbol.TextStyle.Halo.Color = clr;
                break;
              case "marker-line-width":
                if (markSymbol != null)
                  markSymbol.Stroke.Width = Convert.ToSingle(pv.Value);
                else if (glyphSymbol != null)
                  glyphSymbol.TextStyle.Halo.Radius = Convert.ToSingle(pv.Value);
                break;
              case "marker-line-opacity":
                if (markSymbol != null)
                  markSymbol.Stroke.Opacity = Convert.ToSingle(pv.Value);
                else if (glyphSymbol != null)
                  glyphSymbol.TextStyle.Halo.Opacity = Convert.ToSingle(pv.Value);
                break;
              case "marker-placement":
                lpi.Placement = pv.Value;
                if ((glyphSymbol != null || markSymbol != null) && lpi.Placement.Equals("line"))
                  lpi.Placement = "line-point-pattern";
                break;
              case "marker-multi-policy":
                // TODO
                break;
              case "marker-type":
                markSymbol.WellKnownName = pv.Value;
                break;
              case "marker-width":
                width = Convert.ToSingle(pv.Value);
                if (glyphSymbol != null)
                  glyphSymbol.TextStyle.Font.Size = width;
                break;
              case "marker-height":
                height = Convert.ToSingle(pv.Value);
                break;
              case "marker-fill-opacity":
                if (markSymbol != null)
                  markSymbol.Fill.Opacity = Convert.ToSingle(pv.Value);
                else if (glyphSymbol != null)
                  glyphSymbol.TextStyle.Opacity = Convert.ToSingle(pv.Value);
                break;
              case "marker-fill":
                clr = ColorUtility.FromHtml(pv.Value);
                if (markSymbol != null)
                  markSymbol.Fill.Color = clr;
                else if (glyphSymbol != null)
                  glyphSymbol.TextStyle.Color = clr;
                break;
              case "marker-allow-overlap":
                symPoint.LabelBehaviour.AllowOverlap = Convert.ToBoolean(pv.Value);
                break;
              case "marker-ignore-placement":
                symPoint.LabelBehaviour.CollisionDetectable = !Convert.ToBoolean(pv.Value);
                break;
              case "marker-spacing":
                lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
                break;
              case "marker-max-error":
                // TODO
                break;
              case "marker-transform":
                ApplySVGTransformation(symPoint.Graphic, pv.Value);
                break;
              case "marker-clip":
                symPoint.Clip = Convert.ToBoolean(pv.Value);
                break;
              case "marker-smooth":
                symPoint.Clip = Convert.ToBoolean(pv.Value);
                break;
              case "marker-geometry-transform":
                UnsupportedProperty(pv);
                break;
              case "marker-comp-op":
                UnsupportedProperty(pv);
                AddProperty(symPoint, "comp-op", pv.Value);
                break;
            }
          }
        }
      }
      catch (Exception ex)
      {
        ThrowParsingException(ex, pv);
      }

      if (height == 0F)
        height = width;

      if (markSymbol != null)
        markSymbol.Size = new SizeF(width, height);
      else if (glyphSymbol != null)
        symPoint.Graphic.Size = new SizeF(width, 6);

      symPoint.LabelPlacement = CreateLabelPlacement(lpi);

      return symPoint;
    }
    private TextSymbolizer CreateTextSymbolizer(NodePropertyValue[] properties)
    {
      TextSymbolizer symText = new TextSymbolizer();
      symText.Clip = true;
      symText.TextLayout.Alignment = TextAlignment.CenterAligned;

      GeometryTransformInfo geomTrans = new GeometryTransformInfo();
      LabelPlacementInfo lpi = new LabelPlacementInfo();
      lpi.Symbolizer = (int)SymbolizerType.Text;
      TextLayoutBlock textBlock = new TextLayoutBlock();
      string textTransform = null;
      int blockIndex = -1;
      int nProps = properties.Length;

      NodePropertyValue pv = null;

      try
      {
        for (int i = 0; i < nProps; i++)
        {
          pv = properties[i];

          switch (pv.Name)
          {
            case "text-name":
              if (pv.Value != null)
              {
                string textExpr = ToExpression(pv.Value);
                if (!string.IsNullOrEmpty(textTransform))
                  textExpr = GetTextTransform(textExpr, textTransform);
                textBlock.TextExpression = textExpr;

                // TODO
                if (textBlock.TextExpression == string.Empty)
                  symText.Enabled = false;

                blockIndex++;
                if (blockIndex > 0)
                  textBlock = new TextLayoutBlock();

                symText.TextLayout.Blocks.Add(textBlock);
              }
              break;
            case "text-face-name":
              SetFontName(textBlock, pv.Value);
              break;
            case "text-transform":
              if (string.IsNullOrEmpty(textBlock.TextExpression))
                textTransform = pv.Value;
              else
                textBlock.TextExpression = GetTextTransform(textBlock.TextExpression, pv.Value);
              break;
            case "text-fill":
              Color clr = ColorUtility.FromHtml(pv.Value);
              textBlock.TextFormat.TextStyle.Color = clr;
              if (clr.A != 255)
                textBlock.TextFormat.TextStyle.Opacity = clr.A / 255.0F;
              break;
            case "text-opacity":
              textBlock.TextFormat.TextStyle.Opacity = Convert.ToSingle(pv.Value);
              break;
            case "text-size":
              textBlock.TextFormat.TextStyle.Font.Size = Convert.ToSingle(pv.Value);
              break;
            case "text-halo-radius":
              textBlock.TextFormat.TextStyle.Halo.Radius = Convert.ToSingle(pv.Value);
              break;
            case "text-halo-fill":
              Color clr2 = ColorUtility.FromHtml(pv.Value);
              textBlock.TextFormat.TextStyle.Halo.Color = clr2;
              if (clr2.A != 255)
                textBlock.TextFormat.TextStyle.Halo.Opacity = clr2.A / 255F;
              break;
            case "text-halo-opacity": // This property does not exist in the specification.
              textBlock.TextFormat.TextStyle.Halo.Opacity = Convert.ToSingle(pv.Value);
              break;
            case "text-halo-rasterizer":
              // TODO
              break;
            case "text-ratio":
              //TODO
              break;
            case "text-clip":
              symText.Clip = Convert.ToBoolean(pv.Value);
              break;
            case "text-align":
              textBlock.TextFormat.TextAlignment = ToTextAlignment(pv.Value);
              break;
            case "text-horizontal-alignment":
              // TODO
              break;
            case "text-vertical-alignment":
              // TODO
              break;
            case "text-wrap-width":
              textBlock.TextFormat.TextWrapping.MaxWidth = Convert.ToUInt32(pv.Value);
              textBlock.TextFormat.TextWrapping.Mode = Drawing.Text.TextWrapMode.WrapByMaxWidthPixels;
              break;
            case "text-wrap-before":
              TextWrapping tw = textBlock.TextFormat.TextWrapping;
              if (tw.Characters == null || tw.Characters.Length == 0)
                tw.Characters = new WrapCharacter[] { new WrapCharacter() };
              tw.Characters[0].WrapType = CharacterWrapType.Before;
              break;
            case "text-wrap-character":
              TextWrapping tw2 = textBlock.TextFormat.TextWrapping;
              if (tw2.Characters == null || tw2.Characters.Length == 0)
                tw2.Characters = new WrapCharacter[] { new WrapCharacter() };
              tw2.Characters[0].Character = pv.Value;
              break;
            case "text-character-spacing":
              textBlock.TextFormat.TextSpacing.CharacterSpacing = Convert.ToSingle(pv.Value);
              break;
            case "text-line-spacing":
              textBlock.TextFormat.TextSpacing.Leading = Convert.ToSingle(pv.Value);
              break;
            case "text-allow-overlap":
              symText.LabelBehaviour.AllowOverlap = Convert.ToBoolean(pv.Value);
              break;
            case "text-min-distance":
              symText.LabelBehaviour.CollisionMeasures.Add(string.Format("MinimumDistance({0})", pv.Value));
              break;
            case "text-avoid-edges":
              symText.LabelBehaviour.AvoidEdges = Convert.ToBoolean(pv.Value);
              break;
            case "text-spacing":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "text-max-char-angle-delta":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "text-label-position-tolerance":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "text-min-padding":
              UnsupportedProperty(pv);
              break;
            case "text-min-path-length":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "text-orientation":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "text-placement":
              lpi.Placement = pv.Value;
              if (lpi.Placement == "line")
                geomTrans.OffsetCurve = true;
              break;
            case "text-placement-type":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "text-placements":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "text-dx":
              geomTrans.DisplacementX = pv.Value;
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "text-dy":
              geomTrans.DisplacementY = pv.Value;
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "text-comp-op":
              UnsupportedProperty(pv);
              break;
            default:
              break;
          }
        }
      }
      catch (Exception ex)
      {
        ThrowParsingException(ex, pv);
      }

      ApplyTextBlockFormat(symText.TextLayout);
      symText.LabelPlacement = CreateLabelPlacement(lpi);
      if ("point".Equals(lpi.Placement))
        geomTrans.DisplacementX = geomTrans.DisplacementY = string.Empty;
      symText.GeometryExpression = ToGeometryExpression(geomTrans);

      return symText;
    }
    private LinePatternSymbolizer CreateLinePatternSymbolizer(NodePropertyValue[] properties)
    {
      LinePatternSymbolizer symLinePattern = new LinePatternSymbolizer();
      symLinePattern.Clip = true;
      symLinePattern.LabelBehaviour.AllowOverlap = true;
      symLinePattern.LabelBehaviour.CollisionDetectable = false;

      GeometryTransformInfo geomTrans = new GeometryTransformInfo();
      int nProps = properties.Length;

      NodePropertyValue pv = null;

      try
      {
        for (int i = 0; i < nProps; i++)
        {
          pv = properties[i];

          switch (pv.Name)
          {
            case "line-pattern-file":
              symLinePattern.FileName = ToPath(pv.Value);
              break;
            case "line-pattern-clip":
              symLinePattern.Clip = Convert.ToBoolean(pv.Value);
              break;
            case "line-pattern-simplify":
              geomTrans.Simplify = pv.Value;
              break;
            case "line-pattern-simplify-algorithm":
              geomTrans.SimplifyAlgorithm = pv.Value;
              break;
            case "line-pattern-smooth":
              geomTrans.Smooth = pv.Value;
              break;
            case "line-pattern-offset":
              geomTrans.Offset = pv.Value;
              break;
            case "line-pattern-geometry-transform":
              geomTrans.GeometryTransform = pv.Value;
              break;
            case "line-pattern-comp-op":
             // UnsupportedProperty(pv.Name);
              AddProperty(symLinePattern, "comp-op", pv.Value);
              break;
          }
        }
      }
      catch (Exception ex)
      {
        ThrowParsingException(ex, pv);
      }

      symLinePattern.GeometryExpression = ToGeometryExpression(geomTrans);

      return symLinePattern;
    }
 private void UnsupportedProperty(NodePropertyValue prop)
 {
   if (m_logger != null)
   {
     NotSupportedPropertyException npe = new NotSupportedPropertyException(string.Format("Property '{0}' is not supported.", prop.Name), prop.Location.FileName, Zone.GetLineNumber(prop.Location));
     LogFactory.WriteLogEntry(m_logger, npe, LogEntryType.Information);
   }
 }
 public bool IsSymbolizerPropertyValid(string symbolizer, NodePropertyValue property)
 {
   return m_referencer.IsSymbolizerPropertyValid(symbolizer, property);
 }
    public bool IsSymbolizerPropertyValid(string symbolizer, NodePropertyValue property)
    {
      SymbolizerDescriptor symDesc = null;
      if (m_typesDict.TryGetValue(symbolizer, out symDesc))
      {
        bool bFound = false;
        foreach (string symProperty in symDesc.Properties.Keys)
        {
          if (string.Equals(symProperty, property.Name))
          {
            bFound = true;
            break;
          }
        }

        return bFound;
      }

      return false;
    }
    private RasterSymbolizer CreateRasterSymbolizer(NodePropertyValue[] properties)
    {
      RasterSymbolizer symRaster = new RasterSymbolizer();

      NodePropertyValue pv = null;

      try
      {
        int nProps = properties.Length;
        for (int i = 0; i < nProps; i++)
        {
          pv = properties[i];
          switch (pv.Name)
          {
            case "raster-opacity":
              symRaster.Opacity = Convert.ToSingle(pv.Value);
              break;
            case "raster-filter-factor":
              UnsupportedProperty(pv);
              break;
            case "raster-scaling":
              symRaster.InterpolationMode = ToImageResamplingMode(pv.Value);
              break;
            case "raster-mesh-size":
              UnsupportedProperty(pv);
              break;
            case "raster-comp-op":
              symRaster.CompositingMode = ToCompositingMode(pv.Value);
              break;
            case "raster-colorizer-default-mode":
              symRaster.ColorMap.DefaultMode = ToColorMapMode(pv.Value);
              break;
            case "raster-colorizer-default-color":
              symRaster.ColorMap.DefaultColor = ColorUtility.FromHtml(pv.Value);
              break;
            case "raster-colorizer-epsilon":
              symRaster.ColorMap.Epsilon = Convert.ToSingle(pv.Value);
              break;
            case "raster-colorizer-stops":
              MatchCollection stopsMatch = m_colorMapStops.Matches(pv.Value.ToLower());
              if (stopsMatch.Count > 0)
              {
                symRaster.ShadedRelief.ShaderType = ShaderType.Custom;

                foreach (Match match in stopsMatch)
                {
                  ColorMapEntry entry = new ColorMapEntry();
                  MatchCollection args = m_regexFuncParams.Matches(match.Groups[2].Value.Trim(new char[] { '(', ')' }));

                  for (int a = 0; a < args.Count; a++)
                  {
                    Match arg = args[a];
                    string av = arg.Value.Trim();
                    if (a == 0)
                      entry.Quantity = Convert.ToDouble(av);
                    else if (a == 1)
                      entry.Color = ColorUtility.FromHtml(av);
                    else if (a == 2)
                      entry.Mode = ToColorMapMode(av);
                  }

                  symRaster.ColorMap.Entries.Add(entry);
                }
              }
              break;
          }
        }
      }
      catch (Exception ex)
      {
        ThrowParsingException(ex, pv);
      }

      return symRaster;
    }
 private Exception ThrowParsingException(Exception ex, NodePropertyValue pv)
 {
   throw new ParsingException(string.Format("Invalid value '{0}' for property '{1}'.", pv.Value, pv.Name) + " " + ex.Message, pv.Location.FileName, Zone.GetLineNumber(pv.Location));
 }
 public bool IsSymbolizerPropertyValid(string symbolizer, NodePropertyValue property)
 {
     return(m_referencer.IsSymbolizerPropertyValid(symbolizer, property));
 }
 public bool HasRequiredProperties(string symbolizer, NodePropertyValue[] properties, ref string missingProperty)
 {
   return m_referencer.HasRequiredProperties(symbolizer, properties, ref missingProperty);
 }
    private PolygonSymbolizer CreatePolygonSymbolizer(NodePropertyValue[] properties)
    {
      PolygonSymbolizer symPolygon = new PolygonSymbolizer();
      symPolygon.Fill.Color = Color.Gray;
      symPolygon.Fill.Outlined = false;
      symPolygon.Clip = true;

      GraphicFill gFill = properties[0].Name.StartsWith("polygon-pattern-") ? new GraphicFill() : null;
      if (gFill != null)
      {
        symPolygon.Fill.GraphicFill = gFill;
        symPolygon.Fill.Opacity = 0.0F;
      }

      GeometryTransformInfo geomTrans = new GeometryTransformInfo();

      NodePropertyValue pv = null;

      try
      {
        int nProps = properties.Length;

        for (int i = 0; i < nProps; i++)
        {
          pv = properties[i];

          if (gFill != null)
          {
            switch (pv.Name)
            {
              case "polygon-pattern-file":
                ExternalGraphicSymbol egs = new ExternalGraphicSymbol();
                egs.Path = ToPath(pv.Value);
                gFill.GraphicSymbols.Add(egs);
                break;
              case "polygon-pattern-opacity":
                gFill.Opacity = Convert.ToSingle(pv.Value);
                break;
              case "polygon-pattern-comp-op":
                AddProperty(symPolygon, "comp-op", pv.Value);
                break;
            }
          }
          else
          {
            switch (pv.Name)
            {
              case "polygon-fill":
                Color clr = ColorUtility.FromHtml(pv.Value);
                symPolygon.Fill.Color = clr;
                if (clr.A != 255)
                  symPolygon.Fill.Opacity = clr.A / 255.0F;
                break;
              case "polygon-opacity":
                symPolygon.Fill.Opacity = Convert.ToSingle(pv.Value);
                break;
              case "polygon-gamma":
                UnsupportedProperty(pv);
                break;
              case "polygon-gamma-method":
                UnsupportedProperty(pv);
                break;
              case "polygon-clip":
                symPolygon.Clip = Convert.ToBoolean(pv.Value);
                break;
              case "polygon-comp-op":
                UnsupportedProperty(pv);
                AddProperty(symPolygon, "comp-op", pv.Value);
                break;
              case "polygon-simplify":
                geomTrans.Simplify = pv.Value;
                break;
              case "polygon-simplify-algorithm":
                geomTrans.SimplifyAlgorithm = pv.Value;
                break;
              case "polygon-smooth":
                geomTrans.Smooth = pv.Value;
                break;
              case "polygon-offset":
                geomTrans.Offset = pv.Value;
                break;
              case "polygon-geometry-transform":
                geomTrans.GeometryTransform = pv.Value;
                break;
            }
          }
        }
      }
      catch (Exception ex)
      {
        ThrowParsingException(ex, pv);
      }

      symPolygon.GeometryExpression = ToGeometryExpression(geomTrans);

      return symPolygon;
    }
    private static bool HasPropertyValue(NodePropertyValue[] properties, string prop, string value)
    {
      for (int i = 0; i < properties.Length; i++)
      {
        NodePropertyValue pv = properties[i];
        if (pv.Name.Equals(prop, StringComparison.OrdinalIgnoreCase))
        {
          if (pv.Value.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
            return true;
        }
      }

      return false;
    }
    private LineSymbolizer CreateLineSymbolizer(NodePropertyValue[] properties)
    {
      LineSymbolizer symLine = new LineSymbolizer();
      symLine.Stroke.LineCap = System.Drawing.Drawing2D.LineCap.Flat;
      symLine.Stroke.LineJoin = System.Drawing.Drawing2D.LineJoin.Miter;
      symLine.Clip = true;

      GeometryTransformInfo geomTrans = new GeometryTransformInfo();
      NodePropertyValue pv = null;

      try
      {
        int nProps = properties.Length;
        for (int i = 0; i < nProps; i++)
        {
          pv = properties[i];

          switch (pv.Name)
          {
            case "line-width":
              symLine.Stroke.Width = Convert.ToSingle(pv.Value);
              break;
            case "line-color":
              Color clr = ColorUtility.FromHtml(pv.Value);
              symLine.Stroke.Color = clr;
              if (clr.A != 255)
                symLine.Stroke.Opacity = clr.A / 255.0F;
              break;
            case "line-opacity":
              symLine.Stroke.Opacity = Convert.ToSingle(pv.Value);
              break;
            case "line-join":
              symLine.Stroke.LineJoin = ToLineJoin(pv.Value);
              break;
            case "line-cap":
              symLine.Stroke.LineCap = ToLineCap(pv.Value);
              break;
            case "line-dasharray":
              symLine.Stroke.DashArray = ConvertUtility.ToFloatArray(pv.Value);
              break;
            case "line-miterlimit":
              symLine.Stroke.MiterLimit = Convert.ToSingle(pv.Value);
              break;
            case "line-dash-offset":
              symLine.Stroke.DashOffset = Convert.ToSingle(pv.Value);
              break;
            case "line-comp-op":
              UnsupportedProperty(pv);
              AddProperty(symLine, "comp-op", pv.Value);
              break;
            case "line-rasterizer":
              UnsupportedProperty(pv);
              break;
            case "line-simplify":
              geomTrans.Simplify = pv.Value;
              break;
            case "line-simplify-algorithm":
              geomTrans.SimplifyAlgorithm = pv.Value;
              break;
            case "line-smooth":
              geomTrans.Smooth = pv.Value;
              break;
            case "line-offset":
              geomTrans.Offset = pv.Value;
              break;
            case "line-geometry-transform":
              geomTrans.GeometryTransform = pv.Value;
              break;
          }
        }
      }
      catch(Exception ex)
      {
        ThrowParsingException(ex, pv);
      }

      symLine.GeometryExpression = ToGeometryExpression(geomTrans);

      return symLine;
    }
    private GraphicTextSymbolizer CreateGraphicTextSymbolizer(NodePropertyValue[] properties)
    {
      GraphicTextSymbolizer symText = new GraphicTextSymbolizer();
      symText.Clip = true;
      symText.TextLayout.Alignment = TextAlignment.CenterAligned;
      ExternalGraphicSymbol gsImage = new ExternalGraphicSymbol();
      symText.Graphic.GraphicSymbols.Add(gsImage);

      GeometryTransformInfo geomTrans = new GeometryTransformInfo();

      LabelPlacementInfo lpi = new LabelPlacementInfo();
      lpi.Placement = "point";
      lpi.Symbolizer = (int)SymbolizerType.Shield;

      int blockIndex = -1;
      TextLayoutBlock textBlock = new TextLayoutBlock();
      string textTransform = null;
      int nProps = properties.Length;
      float text_dx = 0F, text_dy = 0F;

      NodePropertyValue pv = null;

      try
      {
        for (int i = 0; i < nProps; i++)
        {
          pv = properties[i];

          switch (pv.Name)
          {
            case "shield-name":
              if (pv.Value != null)
              {
                string textExpr = ToExpression(pv.Value);
                if (!string.IsNullOrEmpty(textTransform))
                  textExpr = GetTextTransform(textExpr, textTransform);
                textBlock.TextExpression = textExpr;

                blockIndex++;
                if (blockIndex > 0)
                  textBlock = new TextLayoutBlock();

                symText.TextLayout.Blocks.Add(textBlock);
              }
              break;
            case "shield-face-name":
              SetFontName(textBlock, pv.Value);
              break;
            case "shield-file":
              gsImage.Path = ToPath(pv.Value);
              break;
            case "shield-text-transform":
              if (string.IsNullOrEmpty(textBlock.TextExpression))
                textTransform = pv.Value;
              else
                textBlock.TextExpression = GetTextTransform(textBlock.TextExpression, pv.Value);
              break;
            case "shield-fill":
              textBlock.TextFormat.TextStyle.Color = ColorUtility.FromHtml(pv.Value);
              break;
            case "shield-text-opacity":
              textBlock.TextFormat.TextStyle.Opacity = Convert.ToSingle(pv.Value);
              break;
            case "shield-opacity":
              gsImage.Opacity = Convert.ToSingle(pv.Value);
              break;
            case "shield-size":
              textBlock.TextFormat.TextStyle.Font.Size = Convert.ToSingle(pv.Value);
              break;
            case "shield-halo-radius":
              textBlock.TextFormat.TextStyle.Halo.Radius = Convert.ToSingle(pv.Value);
              break;
            case "shield-halo-fill":
              Color clr = ColorUtility.FromHtml(pv.Value);
              textBlock.TextFormat.TextStyle.Halo.Color = clr;
              if (clr.A != 255)
                textBlock.TextFormat.TextStyle.Halo.Opacity = clr.A / 255.0F;
              break;
            case "shield-halo-opacity":
              textBlock.TextFormat.TextStyle.Halo.Opacity = Convert.ToSingle(pv.Value);
              break;
            case "shield-clip":
              symText.Clip = Convert.ToBoolean(pv.Value);
              break;
            case "shield-horizontal-alignment":
              // TODO
              break;
            case "shield-vertical-alignment":
              // TODO
              break;
            case "shield-justify-alignment":
              // TODO
              break;
            case "shield-transform":
              //TODO
              break;
            case "shield-wrap-width":
              textBlock.TextFormat.TextWrapping.MaxWidth = Convert.ToUInt32(pv.Value);
              textBlock.TextFormat.TextWrapping.Mode = Drawing.Text.TextWrapMode.WrapByMaxWidthPixels;
              break;
            case "shield-wrap-before":
              TextWrapping tw = textBlock.TextFormat.TextWrapping;
              if (tw.Characters == null)
                tw.Characters = new WrapCharacter[] { new WrapCharacter() };

              tw.Characters[0].WrapType = CharacterWrapType.Before;
              break;
            case "shield-wrap-character":
              TextWrapping tw2 = textBlock.TextFormat.TextWrapping;
              if (tw2.Characters == null)
                tw2.Characters = new WrapCharacter[] { new WrapCharacter() };

              tw2.Characters[0].Character = pv.Value;
              break;
            case "shield-character-spacing":
              textBlock.TextFormat.TextSpacing.CharacterSpacing = Convert.ToSingle(pv.Value);
              break;
            case "shield-line-spacing":
              textBlock.TextFormat.TextSpacing.Leading = Convert.ToSingle(pv.Value);
              break;
            case "shield-allow-overlap":
              symText.LabelBehaviour.AllowOverlap = Convert.ToBoolean(pv.Value);
              break;
            case "shield-min-distance":
              symText.LabelBehaviour.CollisionMeasures.Add(string.Format("MinimumDistance({0})", pv.Value));
              break;
            case "shield-avoid-edges":
              symText.LabelBehaviour.AvoidEdges = Convert.ToBoolean(pv.Value);
              break;
            case "shield-spacing":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "shield-min-padding":
              UnsupportedProperty(pv);
              break;
            case "shield-placement-type":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "shield-placements":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "shield-text-dx":
              text_dx = Convert.ToSingle(pv.Value);
              break;
            case "shield-text-dy":
              text_dy = Convert.ToSingle(pv.Value);
              break;
            case "shield-dx":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "shield-dy":
              lpi.Properties.Add(new KeyValuePair<string, string>(pv.Name, pv.Value));
              break;
            case "shield-comp-op":
              UnsupportedProperty(pv);
              break;
            default:
              break;
          }
        }
      }
      catch (Exception ex)
      {
        ThrowParsingException(ex, pv);
      }

      if (text_dx != 0F || text_dy != 0F)
        symText.Graphic.Size = new SizeF(text_dx, text_dy);

      ApplyTextBlockFormat(symText.TextLayout);
      symText.LabelPlacement = CreateLabelPlacement(lpi);
      if ("point".Equals(lpi.Placement))
        geomTrans.DisplacementX = geomTrans.DisplacementY = string.Empty;
      symText.GeometryExpression = ToGeometryExpression(geomTrans);

      return symText;
    }
    public bool HasRequiredProperties(string symbolizer, NodePropertyValue[] properties, ref string missingProperty)
    {
      SymbolizerDescriptor symDesc = null;
      if (m_typesDict.TryGetValue(symbolizer, out symDesc))
      {
        foreach (string key in symDesc.Properties.Keys)
        {
          CartoPropertyInfo cpi = symDesc.Properties[key];
          if (cpi.Required)
          {
            bool bFound = false;

            foreach (NodePropertyValue prop in properties)
            {
              if (string.Equals(cpi.CssName, prop.Name))
              {
                bFound = true;
                break;
              }
            }

            if (!bFound)
            {
              missingProperty = cpi.CssName;
              return false;
            }
          }
        }
      }

      return true;
    }
 public abstract Symbolizer ToSymbolizer(string symbolizer, NodePropertyValue[] properties);