/// <summary> /// Read points array from XML. /// </summary> /// <returns></returns> PointF[] ReadPoints(XmlInput xmlinput) { List <PointF> points = new List <PointF>(); bool first = true; while (xmlinput.FindSubElement(first, new string[] { "point" })) { points.Add(new PointF(xmlinput.GetAttributeFloat("x"), xmlinput.GetAttributeFloat("y"))); xmlinput.Skip(); first = false; } return(points.ToArray()); }
/// <summary> /// Read points array from XML. /// </summary> /// <returns></returns> PointF[] ReadPoints(XmlInput xmlinput) { List<PointF> points = new List<PointF>(); bool first = true; while (xmlinput.FindSubElement(first, new string[] { "point" })) { points.Add(new PointF(xmlinput.GetAttributeFloat("x"), xmlinput.GetAttributeFloat("y"))); xmlinput.Skip(); first = false; } return points.ToArray(); }
/// <summary> /// Read the state of this symbol from XML. The xmlinput must be on a /// symbol node. /// </summary> public void ReadXml(XmlInput xmlinput) { xmlinput.CheckElement("symbol"); this.kind = xmlinput.GetAttributeString("kind")[0]; this.id = xmlinput.GetAttributeString("id"); this.sizeIsDepth = xmlinput.GetAttributeBool("size-is-depth", false); bool first = true; List<SymbolStroke> strokes = new List<SymbolStroke>(); while (xmlinput.FindSubElement(first, new string[] { "name", "text", "filled-circle", "circle", "polygon", "filled-polygon", "lines", "beziers", "filled-beziers" })) { SymbolStroke stroke = new SymbolStroke(); bool isStroke = true; switch (xmlinput.Name) { case "name": xmlinput.CheckElement("name"); string language = xmlinput.GetAttributeString("lang"); name.Add(language, xmlinput.GetContentString()); isStroke = false; break; case "text": xmlinput.CheckElement("text"); SymbolText symtext = new SymbolText(); symtext.ReadXml(xmlinput); texts.Add(symtext); isStroke = false; break; case "filled-circle": xmlinput.CheckElement("filled-circle"); stroke.kind = SymbolStrokes.Disc; stroke.radius = xmlinput.GetAttributeFloat("radius"); break; case "circle": xmlinput.CheckElement("circle"); stroke.kind = SymbolStrokes.Circle; stroke.thickness = xmlinput.GetAttributeFloat("thickness"); stroke.radius = xmlinput.GetAttributeFloat("radius"); break; case "polygon": xmlinput.CheckElement("polygon"); stroke.kind = SymbolStrokes.Polygon; stroke.thickness = xmlinput.GetAttributeFloat("thickness"); stroke.corners = ToLineJoin(xmlinput.GetAttributeString("corners", "round"), xmlinput); break; case "filled-polygon": xmlinput.CheckElement("filled-polygon"); stroke.kind = SymbolStrokes.FilledPolygon; break; case "lines": xmlinput.CheckElement("lines"); stroke.kind = SymbolStrokes.Polyline; stroke.thickness = xmlinput.GetAttributeFloat("thickness"); stroke.ends = ToLineCap(xmlinput.GetAttributeString("ends", "round"), xmlinput); stroke.corners = ToLineJoin(xmlinput.GetAttributeString("corners", "round"), xmlinput); break; case "beziers": xmlinput.CheckElement("beziers"); stroke.kind = SymbolStrokes.PolyBezier; stroke.thickness = xmlinput.GetAttributeFloat("thickness"); stroke.ends = ToLineCap(xmlinput.GetAttributeString("ends", "round"), xmlinput); break; case "filled-beziers": xmlinput.CheckElement("filled-beziers"); stroke.kind = SymbolStrokes.FilledPolyBezier; break; } if (isStroke) { stroke.points = ReadPoints(xmlinput); strokes.Add(stroke); } first = false; } if (this.name == null) xmlinput.BadXml("Missing name element"); if (texts.Count == 0) xmlinput.BadXml("Missing text element"); this.strokes = strokes.ToArray(); }
/// <summary> /// Read the state of this symbol from XML. The xmlinput must be on a /// symbol node. /// </summary> public void ReadXml(XmlInput xmlinput) { xmlinput.CheckElement("symbol"); this.kind = xmlinput.GetAttributeString("kind")[0]; this.id = xmlinput.GetAttributeString("id"); this.replacementId = xmlinput.GetAttributeString("replacement-id", null); this.sizeIsDepth = xmlinput.GetAttributeBool("size-is-depth", false); string standardStrings = xmlinput.GetAttributeString("standard", ""); if (standardStrings != "") { this.standards = standardStrings.Split(','); } bool first = true; List <SymbolStroke> strokes = new List <SymbolStroke>(); while (xmlinput.FindSubElement(first, new string[] { "name", "text", "filled-circle", "circle", "polygon", "filled-polygon", "lines", "beziers", "filled-beziers" })) { SymbolStroke stroke = new SymbolStroke(); bool isStroke = true; switch (xmlinput.Name) { case "name": xmlinput.CheckElement("name"); string language = xmlinput.GetAttributeString("lang"); name.Add(language, xmlinput.GetContentString()); isStroke = false; break; case "text": xmlinput.CheckElement("text"); SymbolText symtext = new SymbolText(); symtext.ReadXml(xmlinput); texts.Add(symtext); isStroke = false; break; case "filled-circle": xmlinput.CheckElement("filled-circle"); stroke.kind = SymbolStrokes.Disc; stroke.radius = xmlinput.GetAttributeFloat("radius"); break; case "circle": xmlinput.CheckElement("circle"); stroke.kind = SymbolStrokes.Circle; stroke.thickness = xmlinput.GetAttributeFloat("thickness"); stroke.radius = xmlinput.GetAttributeFloat("radius"); break; case "polygon": xmlinput.CheckElement("polygon"); stroke.kind = SymbolStrokes.Polygon; stroke.thickness = xmlinput.GetAttributeFloat("thickness"); stroke.corners = ToLineJoin(xmlinput.GetAttributeString("corners", "round"), xmlinput); break; case "filled-polygon": xmlinput.CheckElement("filled-polygon"); stroke.kind = SymbolStrokes.FilledPolygon; break; case "lines": xmlinput.CheckElement("lines"); stroke.kind = SymbolStrokes.Polyline; stroke.thickness = xmlinput.GetAttributeFloat("thickness"); stroke.ends = ToLineCap(xmlinput.GetAttributeString("ends", "round"), xmlinput); stroke.corners = ToLineJoin(xmlinput.GetAttributeString("corners", "round"), xmlinput); break; case "beziers": xmlinput.CheckElement("beziers"); stroke.kind = SymbolStrokes.PolyBezier; stroke.thickness = xmlinput.GetAttributeFloat("thickness"); stroke.ends = ToLineCap(xmlinput.GetAttributeString("ends", "round"), xmlinput); break; case "filled-beziers": xmlinput.CheckElement("filled-beziers"); stroke.kind = SymbolStrokes.FilledPolyBezier; break; } if (isStroke) { stroke.points = ReadPoints(xmlinput); strokes.Add(stroke); } first = false; } if (this.name == null) { xmlinput.BadXml("Missing name element"); } if (texts.Count == 0) { xmlinput.BadXml("Missing text element"); } this.strokes = strokes.ToArray(); }
public override void ReadAttributesAndContent(XmlInput xmlinput) { string kindText = xmlinput.GetAttributeString("kind"); switch (kindText) { case "normal": kind = ControlPointKind.Normal; break; case "start": kind = ControlPointKind.Start; break; case "finish": kind = ControlPointKind.Finish; break; case "crossing-point": kind = ControlPointKind.CrossingPoint; break; case "map-exchange": kind = ControlPointKind.MapExchange; break; default: xmlinput.BadXml("Invalid control point kind '{0}'", kindText); break; } if (kind == ControlPointKind.Normal || kind == ControlPointKind.Start || kind == ControlPointKind.MapExchange) symbolIds = new string[6]; else if (kind == ControlPointKind.Finish || kind == ControlPointKind.CrossingPoint) symbolIds = new string[1]; code = null; descriptionText = null; columnFText = null; // Old file format had a single gaps attribute for all scales. Put this in the dictionary with scale of 0, then update after load is finished. string gapText = xmlinput.GetAttributeString("gaps", ""); if (gapText != "") { uint gapValue = Convert.ToUInt32(gapText, 2); if (gaps == null) gaps = new Dictionary<int, CircleGap[]>(); gaps[0] = CircleGap.ComputeCircleGaps(gapValue); } string codeAngle = xmlinput.GetAttributeString("all-controls-code-angle", ""); if (codeAngle != "") { customCodeLocation = true; codeLocationAngle = XmlConvert.ToSingle(codeAngle); } if (kind == ControlPointKind.CrossingPoint) orientation = xmlinput.GetAttributeFloat("orientation"); bool first = true; while (xmlinput.FindSubElement(first, "code", "location", "description", "description-text", "gaps", "circle-gaps", "punch-pattern", "description-text-line")) { switch (xmlinput.Name) { case "code": if (kind != ControlPointKind.Normal) xmlinput.BadXml("Only normal control points can have a code"); code = xmlinput.GetContentString(); break; case "location": float x = xmlinput.GetAttributeFloat("x"); float y = xmlinput.GetAttributeFloat("y"); location = new PointF(x, y); xmlinput.Skip(); break; case "punch-pattern": punches = new PunchPattern(); punches.size = xmlinput.GetAttributeInt("size"); punches.dots = new bool[punches.size, punches.size]; string punchPattern = xmlinput.GetContentString(); int index = 0; for (int i = 0; i < punches.size; ++i) for (int j = 0; j < punches.size; ++j) { char c; do { if (index >= punchPattern.Length) { xmlinput.BadXml("invalid punch pattern"); goto QUITPUNCHPATTERN; } c = punchPattern[index++]; } while (c != '0' && c != '1'); punches.dots[i, j] = (c == '1'); } QUITPUNCHPATTERN: break; case "gaps": { int scale = xmlinput.GetAttributeInt("scale", 0); gapText = xmlinput.GetContentString().Trim(); if (gapText != "") { if (gaps == null) gaps = new Dictionary<int, CircleGap[]>(); if (gapText.Contains(":")) { // For 2.0 beta 1 compatibility only. gaps[scale] = CircleGap.DecodeGaps(gapText); } else if (!gaps.ContainsKey(scale)) { // Only use the old-style if the new-style wasn't found. uint gapValue = Convert.ToUInt32(gapText, 2); gaps[scale] = CircleGap.ComputeCircleGaps(gapValue); } } break; } case "circle-gaps": { int scale = xmlinput.GetAttributeInt("scale", 0); gapText = xmlinput.GetContentString().Trim(); if (gapText != "") { if (gaps == null) gaps = new Dictionary<int, CircleGap[]>(); if (gapText.Contains(":")) { // This is the new-style; overrides old style if both present. gaps[scale] = CircleGap.DecodeGaps(gapText); } } break; } case "description-text": descriptionText = xmlinput.GetContentString(); break; case "description-text-line": xmlinput.CheckElement("description-text-line"); string locationText = xmlinput.GetAttributeString("location"); if (locationText == "before") descTextBefore = xmlinput.GetContentString(); else if (locationText == "after") descTextAfter = xmlinput.GetContentString(); else { xmlinput.BadXml("location attribute on description-text-line must be \"before\" or \"after\""); xmlinput.Skip(); } break; case "description": string box = xmlinput.GetAttributeString("box"); string symbolId = xmlinput.GetAttributeString("iof-2004-ref", null); string text = xmlinput.GetContentString(); switch (box) { case "all": symbolIds[0] = symbolId; break; case "C": symbolIds[0] = symbolId; break; case "D": symbolIds[1] = symbolId; break; case "E": symbolIds[2] = symbolId; break; case "F": symbolIds[3] = symbolId; break; case "G": symbolIds[4] = symbolId; break; case "H": symbolIds[5] = symbolId; break; default: xmlinput.BadXml("Invalid box type '{0}'", box); break; } if (box == "F" && !string.IsNullOrEmpty(text)) columnFText = text; break; } first = false; } }
public override void ReadAttributesAndContent(XmlInput xmlinput) { string kindText = xmlinput.GetAttributeString("kind"); switch (kindText) { case "normal": kind = CourseKind.Normal; break; case "score": kind = CourseKind.Score; break; default: xmlinput.BadXml("Invalid course kind '{0}'", kindText); break; } sortOrder = xmlinput.GetAttributeInt("order", 0); // 0 sort orders fixed up later in EventDB.FixCourseSortOrders() name = ""; printScale = 15000; descKind = DescriptionKind.Symbols; firstCourseControl = Id<CourseControl>.None; firstControlOrdinal = 1; labelKind = (kind == CourseKind.Score) ? ControlLabelKind.Code : ControlLabelKind.Sequence; scoreColumn = (kind == CourseKind.Score) ? 0 : -1; bool first = true; while (xmlinput.FindSubElement(first, "name", "secondary-title", "first", "print-area", "options", "labels", "part-options", "relay")) { switch (xmlinput.Name) { case "name": name = xmlinput.GetContentString(); break; case "secondary-title": secondaryTitle = xmlinput.GetContentString(); break; case "first": firstCourseControl = new Id<CourseControl>(xmlinput.GetAttributeInt("course-control")); firstControlOrdinal = xmlinput.GetAttributeInt("control-number", 1); xmlinput.Skip(); break; case "print-area": PrintArea area = new PrintArea(); int part = xmlinput.GetAttributeInt("part", -1); area.ReadAttributesAndContent(xmlinput); if (part == -1) printArea = area; else partPrintAreas[part] = area; break; case "options": printScale = xmlinput.GetAttributeFloat("print-scale"); climb = xmlinput.GetAttributeFloat("climb", -1F); load = xmlinput.GetAttributeInt("load", -1); if (kind == CourseKind.Score) scoreColumn = EventDBUtil.ReadScoreColumnAttribute(xmlinput); descKind = EventDBUtil.ReadDescriptionKindAttribute(xmlinput); float len = xmlinput.GetAttributeFloat("course-length", -1F); if (len > 0) overrideCourseLength = len; else overrideCourseLength = null; xmlinput.Skip(); break; case "part-options": part = xmlinput.GetAttributeInt("part", -1); bool showFinish = xmlinput.GetAttributeBool("show-finish"); if (part != -1) partOptions[part] = new PartOptions() { ShowFinish = showFinish }; xmlinput.Skip(); break; case "labels": string labelKindText = xmlinput.GetAttributeString("label-kind"); switch (labelKindText) { case "sequence": labelKind = ControlLabelKind.Sequence; break; case "code": labelKind = ControlLabelKind.Code; break; case "sequence-and-code": labelKind = ControlLabelKind.SequenceAndCode; break; case "sequence-and-score": labelKind = ControlLabelKind.SequenceAndScore; break; case "code-and-score": labelKind = ControlLabelKind.CodeAndScore; break; default: labelKind = ControlLabelKind.Sequence; break; } xmlinput.Skip(); break; case "relay": relayTeams = xmlinput.GetAttributeInt("teams", 0); relayLegs = xmlinput.GetAttributeInt("legs", 1); xmlinput.Skip(); break; } first = false; } if (printArea == null) printArea = PrintArea.DefaultPrintArea; }
public override void ReadAttributesAndContent(XmlInput xmlinput) { firstControlCode = 31; disallowInvertibleCodes = true; courseAppearance.purpleColorBlend = false; // default for existing events is false, true for new events. printArea = null; // Will be set at end if not loaded. bool first = true; while (xmlinput.FindSubElement(first, "title", "notes", "map", "all-controls", "numbering", "punch-card", "course-appearance", "print-area", "descriptions", "ocad", "custom-symbol-text")) { switch (xmlinput.Name) { case "title": title = xmlinput.GetContentString(); break; case "notes": notes = xmlinput.GetContentString(); break; case "map": mapScale = xmlinput.GetAttributeFloat("scale"); string kindString = xmlinput.GetAttributeString("kind"); switch (kindString) { case "none": mapType = MapType.None; break; case "OCAD": mapType = MapType.OCAD; break; case "bitmap": mapType = MapType.Bitmap; break; case "PDF": mapType = MapType.PDF; break; default: xmlinput.BadXml("Invalid map kind '{0}'", kindString); break; } if (mapType == MapType.Bitmap) mapDpi = xmlinput.GetAttributeFloat("dpi"); else mapDpi = 0; if (mapType == MapType.OCAD) ignoreMissingFonts = xmlinput.GetAttributeBool("ignore-missing-fonts", false); if (mapType != MapType.None) { mapFileName = xmlinput.GetContentString(); mapFileName = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(xmlinput.FileName), mapFileName)); // file name is relative to the XML file } else { mapFileName = null; xmlinput.Skip(); } break; case "all-controls": allControlsPrintScale = xmlinput.GetAttributeFloat("print-scale", 0); allControlsDescKind = EventDBUtil.ReadDescriptionKindAttribute(xmlinput); xmlinput.Skip(); break; case "numbering": firstControlCode = xmlinput.GetAttributeInt("start", 31); disallowInvertibleCodes = xmlinput.GetAttributeBool("disallow-invertible", true); xmlinput.Skip(); break; case "punch-card": punchcardFormat.boxesDown = xmlinput.GetAttributeInt("rows", PunchcardAppearance.defaultBoxesDown); punchcardFormat.boxesAcross = xmlinput.GetAttributeInt("columns", PunchcardAppearance.defaultBoxesAcross); punchcardFormat.leftToRight = xmlinput.GetAttributeBool("left-to-right", PunchcardAppearance.defaultLeftToRight); punchcardFormat.topToBottom = xmlinput.GetAttributeBool("top-to-bottom", PunchcardAppearance.defaultTopToBottom); xmlinput.Skip(); break; case "course-appearance": courseAppearance.controlCircleSize = xmlinput.GetAttributeFloat("control-circle-size-ratio", 1.0F); courseAppearance.lineWidth = xmlinput.GetAttributeFloat("line-width-ratio", 1.0F); courseAppearance.centerDotDiameter = xmlinput.GetAttributeFloat("center-dot-diameter", 0.0F); courseAppearance.numberHeight = xmlinput.GetAttributeFloat("number-size-ratio", 1.0F); courseAppearance.numberBold = xmlinput.GetAttributeBool("number-bold", false); courseAppearance.numberOutlineWidth = xmlinput.GetAttributeFloat("number-outline-width", 0.0F); courseAppearance.autoLegGapSize = xmlinput.GetAttributeFloat("auto-leg-gap-size", 3.5F); // default value courseAppearance.purpleColorBlend = xmlinput.GetAttributeBool("blend-purple", false); courseAppearance.purpleC = xmlinput.GetAttributeFloat("purple-cyan", -1F); courseAppearance.purpleM = xmlinput.GetAttributeFloat("purple-magenta", -1F); courseAppearance.purpleY = xmlinput.GetAttributeFloat("purple-yellow", -1F); courseAppearance.purpleK = xmlinput.GetAttributeFloat("purple-black", -1F); if (courseAppearance.purpleC < 0 || courseAppearance.purpleM < 0 || courseAppearance.purpleY < 0 || courseAppearance.purpleK < 0) { courseAppearance.useDefaultPurple = true; courseAppearance.purpleC = courseAppearance.purpleM = courseAppearance.purpleY = courseAppearance.purpleK = 1; } else { courseAppearance.useDefaultPurple = false; } xmlinput.Skip(); break; case "print-area": printArea = new PrintArea(); printArea.ReadAttributesAndContent(xmlinput); break; case "descriptions": descriptionLangId = xmlinput.GetAttributeString("lang"); string descriptionColor = xmlinput.GetAttributeString("color", "black"); if (descriptionColor.Equals("purple", StringComparison.InvariantCultureIgnoreCase)) courseAppearance.descriptionsPurple = true; else courseAppearance.descriptionsPurple = false; xmlinput.Skip(); break; case "ocad": courseAppearance.useOcadOverprint = xmlinput.GetAttributeBool("overprint-colors", false); xmlinput.Skip(); break; case "custom-symbol-text": string iof2004id = xmlinput.GetAttributeString("iof-2004-ref"); bool key = xmlinput.GetAttributeBool("show-key", false); customSymbolKey[iof2004id] = key; xmlinput.Read(); xmlinput.MoveToContent(); List<SymbolText> texts = new List<SymbolText>(); if (xmlinput.Reader.NodeType == XmlNodeType.Text) { // Reading the old-style custom symbol text. string customText = xmlinput.Reader.ReadString(); if (iof2004id.StartsWith("8.", StringComparison.InvariantCulture)) customText += " {0}"; // old style for modifiers didn't have the fill-in placeholder. SymbolText text = new SymbolText(); text.Lang = "en"; text.Plural = false; text.Gender = ""; text.Text = customText; texts.Add(text); } else { // Read the new-style custom symbol text. while (xmlinput.Reader.NodeType == XmlNodeType.Element && xmlinput.Name == "text") { SymbolText text = new SymbolText(); text.ReadXml(xmlinput); texts.Add(text); xmlinput.Skip(); } } customSymbolText[iof2004id] = texts; xmlinput.Skip(); break; } first = false; } if (allControlsPrintScale == 0) allControlsPrintScale = mapScale; float scaleRatio; if (mapScale > 0 && allControlsPrintScale > 0) scaleRatio = allControlsPrintScale / mapScale; else scaleRatio = 1.0F; if (printArea == null) { printArea = MapUtil.GetDefaultPrintArea(mapFileName, scaleRatio); } }
public void ReadAttributesAndContent(XmlInput xmlinput) { autoPrintArea = xmlinput.GetAttributeBool("automatic", false); restrictToPageSize = xmlinput.GetAttributeBool("restrict-to-page-size", false); float left = xmlinput.GetAttributeFloat("left", float.NaN); float top = xmlinput.GetAttributeFloat("top", float.NaN); float right = xmlinput.GetAttributeFloat("right", float.NaN); float bottom = xmlinput.GetAttributeFloat("bottom", float.NaN); if (float.IsNaN(left) || float.IsNaN(top) || float.IsNaN(right) || float.IsNaN(bottom)) { autoPrintArea = true; printAreaRectangle = new RectangleF(); } else { printAreaRectangle = RectangleF.FromLTRB(left, bottom, right, top); // top and bottom reverse due to map orientation. } pageWidth = xmlinput.GetAttributeInt("page-width", -1); pageHeight = xmlinput.GetAttributeInt("page-height", -1); pageMargins = xmlinput.GetAttributeInt("page-margins", 0); pageLandscape = xmlinput.GetAttributeBool("page-landscape", false); xmlinput.Skip(); }
public override void ReadAttributesAndContent(XmlInput xmlinput) { controlId1 = new Id<ControlPoint>(xmlinput.GetAttributeInt("start-control")); controlId2 = new Id<ControlPoint>(xmlinput.GetAttributeInt("end-control")); bool first = true; while (xmlinput.FindSubElement(first, "flagging", "bends", "gaps")) { switch (xmlinput.Name) { case "flagging": string flagKind = xmlinput.GetAttributeString("kind"); switch (flagKind) { case "none": flagging = FlaggingKind.None; break; case "beginning-part": flagging = FlaggingKind.Begin; break; case "end-part": flagging = FlaggingKind.End; break; case "all": flagging = FlaggingKind.All; break; default: xmlinput.BadXml("Invalid flagging kind '{0}'", flagKind); break; } if (flagging == FlaggingKind.Begin || flagging == FlaggingKind.End) { float x = xmlinput.GetAttributeFloat("x"); float y = xmlinput.GetAttributeFloat("y"); flagStartStop = new PointF(x, y); } xmlinput.Skip(); break; case "bends": bool firstBend = true; List<PointF> locationList = new List<PointF>(); while (xmlinput.FindSubElement(firstBend, "location")) { float x = xmlinput.GetAttributeFloat("x"); float y = xmlinput.GetAttributeFloat("y"); locationList.Add(new PointF(x, y)); xmlinput.Skip(); firstBend = false; } bends = locationList.ToArray(); break; case "gaps": bool firstGap = true; List<LegGap> gapsList = new List<LegGap>(); while (xmlinput.FindSubElement(firstGap, "gap")) { float start = xmlinput.GetAttributeFloat("start"); float length = xmlinput.GetAttributeFloat("length"); gapsList.Add(new LegGap(start, length)); xmlinput.Skip(); firstGap = false; } gaps = gapsList.ToArray(); break; } first = false; } }
public override void ReadAttributesAndContent(XmlInput xmlinput) { string kindText = xmlinput.GetAttributeString("kind"); switch (kindText) { case "first-aid": kind = SpecialKind.FirstAid; break; case "water": kind = SpecialKind.Water; break; case "optional-crossing-point": kind = SpecialKind.OptCrossing; break; case "forbidden-route": kind = SpecialKind.Forbidden; break; case "registration-mark": kind = SpecialKind.RegMark; break; case "boundary": kind = SpecialKind.Boundary; break; case "out-of-bounds": kind = SpecialKind.OOB; break; case "dangerous-area": kind = SpecialKind.Dangerous; break; case "white-out": kind = SpecialKind.WhiteOut; break; case "text": kind = SpecialKind.Text; break; case "descriptions": kind = SpecialKind.Descriptions; break; case "image": kind = SpecialKind.Image; break; case "line": kind = SpecialKind.Line; break; case "rectangle": kind = SpecialKind.Rectangle; break; default: xmlinput.BadXml("Invalid special-object kind '{0}'", kindText); break; } if (kind == SpecialKind.OptCrossing) orientation = xmlinput.GetAttributeFloat("orientation"); text = null; locations = null; allCourses = true; courses = null; imageBitmap = null; List<PointF> locationList = new List<PointF>(); if (kind == SpecialKind.Text || kind == SpecialKind.Line || kind == SpecialKind.Rectangle) color = SpecialColor.Purple; // default color is purple. bool first = true; while (xmlinput.FindSubElement(first, "text", "font", "location", "appearance", "courses", "image-data")) { switch (xmlinput.Name) { case "text": text = xmlinput.GetContentString(); break; case "image-data": // We ignore the format, since Image.FromStream auto-detects. MemoryStream stm = xmlinput.GetContentBase64(); try { imageBitmap = (Bitmap) Image.FromStream(stm); } catch (ArgumentException) { xmlinput.BadXml("Image data could not be loaded"); } break; case "font": fontName = xmlinput.GetAttributeString("name"); fontBold = xmlinput.GetAttributeBool("bold"); fontItalic = xmlinput.GetAttributeBool("italic"); xmlinput.Skip(); break; case "location": float x = xmlinput.GetAttributeFloat("x"); float y = xmlinput.GetAttributeFloat("y"); locationList.Add(new PointF(x, y)); xmlinput.Skip(); break; case "appearance": numColumns = xmlinput.GetAttributeInt("columns", 1); if (kind == SpecialKind.Text || kind == SpecialKind.Line || kind == SpecialKind.Rectangle) { color = xmlinput.GetAttributeColor("color", SpecialColor.Purple); } string lineKindValue = xmlinput.GetAttributeString("line-kind", ""); switch (lineKindValue) { case "single": lineKind = LineKind.Single; break; case "double": lineKind = LineKind.Double; break; case "dashed": lineKind = LineKind.Dashed; break; } lineWidth = xmlinput.GetAttributeFloat("line-width", 0); gapSize = xmlinput.GetAttributeFloat("gap-size", 0); dashSize = xmlinput.GetAttributeFloat("dash-size", 0); if (kind == SpecialKind.Rectangle) cornerRadius = xmlinput.GetAttributeFloat("corner-radius", 0); xmlinput.Skip(); break; case "courses": allCourses = xmlinput.GetAttributeBool("all", false); if (!allCourses) { List<CourseDesignator> courseIdList = new List<CourseDesignator>(); xmlinput.MoveToContent(); bool firstCourse = true; while (xmlinput.FindSubElement(firstCourse, "course")) { int id = xmlinput.GetAttributeInt("course"); int part = xmlinput.GetAttributeInt("part", -1); if (part >= 0) courseIdList.Add(new CourseDesignator(new Id<Course>(id), part)); else courseIdList.Add(new CourseDesignator(new Id<Course>(id))); xmlinput.Skip(); firstCourse = false; } courses = courseIdList.ToArray(); } else { xmlinput.Skip(); } break; } first = false; } if (locationList.Count == 0) xmlinput.BadXml("missing 'location' element"); if ((kind == SpecialKind.Text) && fontName == null) xmlinput.BadXml("missing 'font' element"); if ((kind == SpecialKind.Image) && imageBitmap == null) xmlinput.BadXml("Missing 'image-data' element"); locations = locationList.ToArray(); }
public override void ReadAttributesAndContent(XmlInput xmlinput) { int myId = xmlinput.GetAttributeInt("id"); nextCourseControl = Id<CourseControl>.None; splitCourseControls = null; control = new Id<ControlPoint>(xmlinput.GetAttributeInt("control")); string variationType = xmlinput.GetAttributeString("variation", ""); if (variationType == "fork") { split = true; loop = false; } else if (variationType == "loop") { split = true; loop = true; } else { split = false; } if (split) splitEnd = new Id<CourseControl>(xmlinput.GetAttributeInt("variation-end")); exchange = xmlinput.GetAttributeBool("map-exchange", false); points = xmlinput.GetAttributeInt("points", 0); List<Id<CourseControl>> variationCourseControls = null; bool first = true; while (xmlinput.FindSubElement(first, "next", "variation", "number-location", "description-text-line")) { switch (xmlinput.Name) { case "next": xmlinput.CheckElement("next"); nextCourseControl = new Id<CourseControl>(xmlinput.GetAttributeInt("course-control")); xmlinput.Skip(); break; case "variation": xmlinput.CheckElement("variation"); if (variationCourseControls == null) variationCourseControls = new List<Id<CourseControl>>(); variationCourseControls.Add(new Id<CourseControl>(xmlinput.GetAttributeInt("course-control"))); xmlinput.Skip(); break; case "number-location": xmlinput.CheckElement("number-location"); customNumberPlacement = true; numberDeltaX = xmlinput.GetAttributeFloat("x"); numberDeltaY = xmlinput.GetAttributeFloat("y"); xmlinput.Skip(); break; case "description-text-line": xmlinput.CheckElement("description-text-line"); string location = xmlinput.GetAttributeString("location"); if (location == "before") descTextBefore = xmlinput.GetContentString(); else if (location == "after") descTextAfter = xmlinput.GetContentString(); else { xmlinput.BadXml("location attribute on description-text-line must be \"before\" or \"after\""); xmlinput.Skip(); } break; } first = false; } if (!split && variationCourseControls != null) xmlinput.BadXml("Non-variation course control shouldn't have variation sub-element."); if (variationCourseControls != null) splitCourseControls = variationCourseControls.ToArray(); }