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 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; }
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 LabelPlacement CreateLabelPlacement(LabelPlacementInfo lpi) { LabelPlacement result = null; switch (lpi.Placement) { case "point": case "interior": case "centroid": PointPlacement pp = new PointPlacement(); if (lpi.Placement == "interior") pp.PointOnSurface = true; float dx = 0F, dy = 0F; if (lpi.Symbolizer == (int)SymbolizerType.Text) { pp.Alignments = GetDefaultLabelAlignment(false); foreach (KeyValuePair<string, string> kv in lpi.Properties) { switch (kv.Key) { case "text-dx": dx = Convert.ToSingle(kv.Value); break; case "text-dy": dy = Convert.ToSingle(kv.Value); break; case "text-orientation": pp.AngleExpression = ToExpression(kv.Value); break; case "text-placements": string placementType = lpi.GetPropertyValue("text-placement-type"); if (placementType == "simple") pp.Alignments = ToLabelAlignments(kv.Value); else pp.Alignments = GetDefaultLabelAlignment(false); break; case "text-placement-type": break; } } } else if (lpi.Symbolizer == (int)SymbolizerType.Shield) { pp.Alignments = GetDefaultLabelAlignment(true); float text_dx = 0F, text_dy = 0F; foreach (KeyValuePair<string, string> kv in lpi.Properties) { switch (kv.Key) { case "shield-dx": dx = Convert.ToSingle(kv.Value); break; case "shield-dy": dy = Convert.ToSingle(kv.Value); break; case "shield-placements": string placementType = lpi.GetPropertyValue("shield-placement-type"); if (placementType == "simple") pp.Alignments = ToLabelAlignments(kv.Value); else pp.Alignments = GetDefaultLabelAlignment(true); break; case "shield-placement-type": break; case "shield-text-dx": // text_dx = Convert.ToSingle(kv.Value); break; case "shield-text-dy": // text_dy = Convert.ToSingle(kv.Value); break; } } // TODO text_dx and text_dy } pp.Displacement = new PointF(dx, dy); result = pp; break; case "line": LinePlacement lp = new LinePlacement(); if (lpi.Symbolizer == (int)SymbolizerType.Text) { lp.Spacing = 300; lp.UpsideDownFactorThreshold = 80; foreach (KeyValuePair<string, string> kv in lpi.Properties) { switch (kv.Key) { case "text-min-path-length": lp.MinimumFeatureSize = Convert.ToSingle(kv.Value); break; case "text-spacing": lp.Spacing = Convert.ToSingle(kv.Value); break; case "text-max-char-angle-delta": lp.MaxAngleDelta = Convert.ToSingle(kv.Value); break; case "text-label-position-tolerance": lp.PositionTolerance = Convert.ToSingle(kv.Value); break; } } } else if (lpi.Symbolizer == (int)SymbolizerType.Shield) { foreach (KeyValuePair<string, string> kv in lpi.Properties) { switch (kv.Key) { case "shield-spacing": lp.Spacing = Convert.ToSingle(kv.Value); break; } } } result = lp; break; case "line-point-pattern": LinePointPatternPlacement lppp = new LinePointPatternPlacement(); lppp.Pattern = new float[] { 2, 100 }; foreach (KeyValuePair<string, string> kv in lpi.Properties) { switch (kv.Key) { case "marker-spacing": lppp.Pattern[1] = Convert.ToSingle(kv.Value); break; } } result = lppp; break; case "vertex": throw new NotImplementedException(); default: throw new Exception("Unknown placement type " + lpi.Placement); } return result; }