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();
}