﻿public MainWindow() {
			InitializeComponent();
			if (App.CommandLineArgs.Length > 0) {
				OpenFileMethod(App.CommandLineArgs[0]);
			}
			/*ParserContext pc = new ParserContext();
			pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
			pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
			pc.XmlnsDictionary.Add("CustomControl", "clr-namespace:CourseSetter;assembly=CourseSetter");
			//XmlReader xmlReader = XmlReader.Create("C:\\C#\\CourseSetter\\CourseSetter\\Test.xml",new XmlReaderSettings(),pc);
			XmlTextReader xmlReader = new XmlTextReader("<CustomControl:OControl xmlns:CustomControl=\"clr-namespace:CourseSetter;assembly=CourseSetter\"></CustomControl:OControl>", XmlNodeType.Element, pc);
			OControl test = (OControl)XamlReader.Load(xmlReader);
			*/
			//XmlReader xmlReader = XmlReader.Create("C:\\Misc\\Test.xaml");
			//Viewbox test = (Viewbox)XamlReader.Load(xmlReader);
			//test.RenderTransform = new ScaleTransform(2, 2);
			//TestContent.Content = test;
			//XpsDocument xpsDocument = new XpsDocument("C:\\Misc\\test.xps", System.IO.FileAccess.Read);
			//documentViewer1.Document = xpsDocument.GetFixedDocumentSequence();
		}

		private void OpenTemplate_Click(object sender, RoutedEventArgs e) {
			Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
			dlg.FileName = "";
			dlg.DefaultExt = ".jpg";
			dlg.Filter = "Images (.jpg)|*.jpg";
			Nullable<bool> result = dlg.ShowDialog();
			if (result == true) {
				string filename = dlg.FileName;
				BitmapImage temp = new BitmapImage(new Uri(filename));
				TemplateImage.Source = temp;
				TemplateImage.Width = temp.PixelWidth;
				TemplateImage.Stretch = Stretch.Uniform;
			}
		}

		private void CloseTemplate_Click(object sender, RoutedEventArgs e) {
			TemplateImage.Source = null;
		}

		private void OpenFile_Click(object sender, RoutedEventArgs e) {
			Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
			dlg.FileName = "";
			dlg.DefaultExt = ".xml";
			dlg.Filter = "Images (.xml)|*.xml";
			Nullable<bool> result = dlg.ShowDialog();
			if (result == true) {
				string filename = dlg.FileName;
				OpenFileMethod(filename);
			}
		}

		private void OpenFileMethod(string fileName) {
			XmlReader reader = XmlReader.Create(fileName);
			reader.ReadToFollowing("Template");
			string source = reader.GetAttribute("Source");
			TemplateImage.Source = new BitmapImage(new Uri(source));
		}

		private void button1_Click(object sender, RoutedEventArgs e) {
			Popup1.IsOpen = true;
		}
		
		MemoryStream stream = new MemoryStream();
			Package package = Package.Open(stream, FileMode.Create);
			string inMemoryPackageName = "memorystream://tempXps.xps";
			Uri packageUri = new Uri(inMemoryPackageName);
			PackageStore.AddPackage(packageUri, package);
			XpsDocument xpsDoc = new XpsDocument(package, CompressionOption.SuperFast, inMemoryPackageName);
			PrintToXps(xpsDoc);
			PrintPreview wnd = new PrintPreview();
			wnd.Owner = this;
			wnd.SetPrintDialog(printDialog);
			wnd.SetXpsDoc(xpsDoc);
			wnd.ShowDialog();
			xpsDoc.Close();
			PackageStore.RemovePackage(packageUri);
			package.Close();
			stream.Close();
			
			
			
	public class PrintCleanUpObjects {

		public PrintCleanUpObjects(XpsDocument xpsDoc, Uri packageUri, Package package, MemoryStream stream) {
			this.xpsDoc = xpsDoc;
			this.packageUri = packageUri;
			this.package = package;
			this.stream = stream;
		}

		public void CleanUp() {
			xpsDoc.Close();
			PackageStore.RemovePackage(packageUri);
			package.Close();
			stream.Close();
		}

		XpsDocument xpsDoc;
		Uri packageUri;
		Package package;
		MemoryStream stream;

	}
	
	private Rect GetBoundingRect() {
			if (points.Count == 0) {
				return Rect.Empty;
			}
			double top = points[0].Y;
			double left = points[0].X;
			double bottom = points[0].Y;
			double right = points[0].X;
			for (int i = 1; i < points.Count; i++) {
				if (points[i].X < left) {
					left = points[i].X;
				}
				if (points[i].X > right) {
					right = points[i].X;
				}
				if (points[i].Y < top) {
					top = points[i].Y;
				}
				if (points[i].Y > bottom) {
					bottom = points[i].Y;
				}
			}
			return new Rect(left, top, right - left, bottom - top);
		}

		private Point GetStartOffset() {
			if(points.Count==0){
				return new Point(0,0);
			}
			Rect rect = GetBoundingRect();
			Point centre = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
			Point offsetFromRectCentre = Point.Subtract(points[0], centre);
			return new Point(offsetFromRectCentre.X + x, offsetFromRectCentre.Y + y);
		}

		private List<Point> GetOffsetPoints() {
			List<Point> tempPoints = new List<Point>(points);
			for (int i = 0; i < tempPoints.Count; i++) {
				tempPoints[i].X += x;
				tempPoints[i].Y += y;
			}
			return tempPoints;
		}

		public void AddPoint(Point point) {
			points.Add(point);
		}
		
		
		
		/*protected static PathFigure GetShiftedPath(PathFigure pathFigure, double distance) {
			PathFigure newFigure = new PathFigure();
			Point lastPoint = pathFigure.StartPoint;
			Point currentPoint = new Point(0, 0);
			for (int i = 0; i < pathFigure.Segments.Count; i++) {
				LineSegment lineSegment1 = null;
				BezierSegment bezierSegment1 = null;
				LineSegment lineSegment2 = null;
				BezierSegment bezierSegment2 = null;
				CubicBezierCurveHelper bezierHelper1 = null;
				CubicBezierCurveHelper bezierHelper2 = null;
				lineSegment1 = pathFigure.Segments[i] as LineSegment;
				bezierSegment1 = pathFigure.Segments[i] as BezierSegment;
				if (i < pathFigure.Segments.Count - 1) {
					lineSegment2 = pathFigure.Segments[i + 1] as LineSegment;
					bezierSegment2 = pathFigure.Segments[i + 1] as BezierSegment;
				}
				Vector vector1 = new Vector(0, 0);
				Vector vector2 = new Vector(0, 0);
				double angle1 = 0;
				double angle2 = 0;
				double averageAngle = 0;
				double differenceAverageAngle = 0;
				double distanceFromLine = distance;
				if (lineSegment1 != null) {
					vector1 = Point.Subtract(lineSegment1.Point, lastPoint);
					currentPoint = lineSegment1.Point;
				}
				if (bezierSegment1 != null) {
					bezierHelper1 = new CubicBezierCurveHelper(lastPoint, bezierSegment1.Point1, bezierSegment1.Point2, bezierSegment1.Point3);
					vector1 = bezierHelper1.GetDerivativeAtFractionLength(1);
					currentPoint = bezierSegment1.Point3;
				}
				if (lineSegment2 != null) {
					vector2 = Point.Subtract(lineSegment2.Point, currentPoint);
				}
				if (bezierSegment2 != null) {
					bezierHelper2 = new CubicBezierCurveHelper(currentPoint, bezierSegment2.Point1, bezierSegment2.Point2, bezierSegment2.Point3);
					vector2 = bezierHelper2.GetDerivativeAtFractionLength(0);
				}
				if (vector1.Length > 0) {
					angle1 = Math.Atan2(vector1.Y, vector1.X);
				}
				if (vector2.Length > 0) {
					angle2 = Math.Atan2(vector2.Y, vector2.X);
				}
				if (vector1.Length > 0 && vector2.Length > 0) {
					averageAngle = (angle1 + angle2) / 2;
					differenceAverageAngle = (angle1 - angle2) / 2;
				} else if (vector1.Length > 0) {
					averageAngle = angle1;
				} else if (vector2.Length > 0) {
					averageAngle = angle2;
				}
				if (i == 0) {
					Point start = new Point(lastPoint.X + Math.Sin(angle1) * distance, lastPoint.Y - Math.Cos(angle1) * distance);
					newFigure.StartPoint = start;
				}
				double cosAngle = Math.Cos(differenceAverageAngle);
				if (Math.Abs(cosAngle) < 0.01) {
					cosAngle = Math.Sign(differenceAverageAngle) * 0.01;
				}
				distanceFromLine = distance / cosAngle;
				Point end = new Point(currentPoint.X + Math.Sin(averageAngle) * distanceFromLine, currentPoint.Y - Math.Cos(averageAngle) * distanceFromLine);
				if (lineSegment1 != null) {
					LineSegment segment;
					segment = new LineSegment(end, true);
					newFigure.Segments.Add(segment);
				}
				if (bezierSegment1 != null) {
					BezierSegment segment;
					Vector tangent;
					double angle;
					tangent = bezierHelper1.GetDerivativeAtFractionLength(1.0 / 3.0);
					angle = Math.Atan2(tangent.Y, tangent.X);
					Point point1 = new Point(bezierSegment1.Point1.X + Math.Sin(angle) * distance, bezierSegment1.Point1.Y - Math.Cos(angle) * distance);
					tangent = bezierHelper1.GetDerivativeAtFractionLength(2.0 / 3.0);
					angle = Math.Atan2(tangent.Y, tangent.X);
					Point point2 = new Point(bezierSegment1.Point2.X + Math.Sin(angle) * distance, bezierSegment1.Point2.Y - Math.Cos(angle) * distance);
					segment = new BezierSegment(point1, point2, end, true);
					newFigure.Segments.Add(segment);
				}
				lastPoint = currentPoint;
			}
			return newFigure;
		}

		private static TCord[] ReverseCoords(TCord[] coords) {
			TCord[] result = new TCord[coords.Length];
			for (int i = 0; i < coords.Length; i++) {
				result[coords.Length - 1 - i] = coords[i];
			}
			return result;
		}

		protected static PathFigure GetPointedPath(TCord[] coords, double width, double startPointLength, double endPointLength) {
			PathFigure forwardTempFigure = GetPathData(coords);
			PathFigure backwardTempFigure = GetPathData(ReverseCoords(coords));
			PathFigure forwardFigure = GetPathData(coords);
			PathFigure backwardFigure = GetPathData(ReverseCoords(coords));
			PathFigure newFigure = new PathFigure();
			Point lastPoint = forwardFigure.StartPoint;
			Point currentPoint = new Point(0, 0);
			PathFigureHelper helper;
			helper = new PathFigureHelper(forwardTempFigure);
			double totalLength = helper.GetLength();
			int num = 0;
			if (startPointLength < totalLength) {
				helper.Advance(startPointLength);
				Point point = helper.GetCurrentPoint();
				num += helper.GetCurrentSegmentIndex();
				LineSegment extraSegment = new LineSegment(point, false);
				forwardFigure.Segments.Insert(num, extraSegment);
				num = 1;
			}
			if (endPointLength < totalLength) {
				helper.AdvanceTo(totalLength-endPointLength);
				Point point = helper.GetCurrentPoint();
				num += helper.GetCurrentSegmentIndex();
				LineSegment extraSegment = new LineSegment(point, false);
				forwardFigure.Segments.Insert(num, extraSegment);
			}
			helper = new PathFigureHelper(backwardTempFigure);
			num = 0;
			if (endPointLength < totalLength) {
				helper.Advance(endPointLength);
				Point point = helper.GetCurrentPoint();
				num += helper.GetCurrentSegmentIndex();
				LineSegment extraSegment = new LineSegment(point, false);
				backwardFigure.Segments.Insert(num, extraSegment);
				num = 1;
			}
			if (startPointLength < totalLength) {
				helper.AdvanceTo(totalLength - startPointLength);
				Point point = helper.GetCurrentPoint();
				num += helper.GetCurrentSegmentIndex();
				LineSegment extraSegment = new LineSegment(point, false);
				backwardFigure.Segments.Insert(num, extraSegment);
			}
			double currentDistance;
			helper = new PathFigureHelper(forwardFigure);
			currentDistance = 0;
			for (int i = 0; i < forwardFigure.Segments.Count; i++) {
				LineSegment lineSegment1 = null;
				BezierSegment bezierSegment1 = null;
				LineSegment lineSegment2 = null;
				BezierSegment bezierSegment2 = null;
				CubicBezierCurveHelper bezierHelper1 = null;
				CubicBezierCurveHelper bezierHelper2 = null;
				lineSegment1 = forwardFigure.Segments[i] as LineSegment;
				bezierSegment1 = forwardFigure.Segments[i] as BezierSegment;
				if (i < forwardFigure.Segments.Count - 1) {
					lineSegment2 = forwardFigure.Segments[i + 1] as LineSegment;
					bezierSegment2 = forwardFigure.Segments[i + 1] as BezierSegment;
				}
				Vector vector1 = new Vector(0, 0);
				Vector vector2 = new Vector(0, 0);
				double angle1 = 0;
				double angle2 = 0;
				double averageAngle = 0;
				double differenceAverageAngle = 0;
				double distanceFromLine = width/2;
				double currentLength = 0;
				if (lineSegment1 != null) {
					vector1 = Point.Subtract(lineSegment1.Point, lastPoint);
					currentPoint = lineSegment1.Point;
					currentLength = vector1.Length;
				}
				if (bezierSegment1 != null) {
					bezierHelper1 = new CubicBezierCurveHelper(lastPoint, bezierSegment1.Point1, bezierSegment1.Point2, bezierSegment1.Point3);
					vector1 = bezierHelper1.GetDerivativeAtFractionLength(1);
					currentPoint = bezierSegment1.Point3;
					currentLength = bezierHelper1.GetLength();
				}
				currentDistance += currentLength;
				if (currentDistance < startPointLength) {
					distanceFromLine *= currentDistance / startPointLength;
				} else if (currentDistance > totalLength - endPointLength) {
					distanceFromLine *= (totalLength - currentDistance) / endPointLength;
				}
				if (lineSegment2 != null) {
					vector2 = Point.Subtract(lineSegment2.Point, currentPoint);
				}
				if (bezierSegment2 != null) {
					bezierHelper2 = new CubicBezierCurveHelper(currentPoint, bezierSegment2.Point1, bezierSegment2.Point2, bezierSegment2.Point3);
					vector2 = bezierHelper2.GetDerivativeAtFractionLength(0);
				}
				if (vector1.Length > 0) {
					angle1 = Math.Atan2(vector1.Y, vector1.X);
				}
				if (vector2.Length > 0) {
					angle2 = Math.Atan2(vector2.Y, vector2.X);
				}
				if (vector1.Length > 0 && vector2.Length > 0) {
					averageAngle = (angle1 + angle2) / 2;
					differenceAverageAngle = (angle1 - angle2) / 2;
				} else if (vector1.Length > 0) {
					averageAngle = angle1;
				} else if (vector2.Length > 0) {
					averageAngle = angle2;
				}
				if (i == 0) {
					Point start = new Point(lastPoint.X, lastPoint.Y);
					newFigure.StartPoint = start;
				}
				double cosAngle = Math.Cos(differenceAverageAngle);
				if (Math.Abs(cosAngle) < 0.01) {
					cosAngle = Math.Sign(differenceAverageAngle) * 0.01;
				}
				Point end = new Point(currentPoint.X + Math.Sin(averageAngle) * distanceFromLine / cosAngle, currentPoint.Y - Math.Cos(averageAngle) * distanceFromLine / cosAngle);
				if (lineSegment1 != null) {
					LineSegment segment;
					segment = new LineSegment(end, true);
					newFigure.Segments.Add(segment);
				}
				if (bezierSegment1 != null) {
					BezierSegment segment;
					Vector tangent;
					double angle;
					tangent = bezierHelper1.GetDerivativeAtFractionLength(1.0 / 3.0);
					angle = Math.Atan2(tangent.Y, tangent.X);
					Point point1 = new Point(bezierSegment1.Point1.X + Math.Sin(angle) * distanceFromLine, bezierSegment1.Point1.Y - Math.Cos(angle) * distanceFromLine);
					tangent = bezierHelper1.GetDerivativeAtFractionLength(2.0 / 3.0);
					angle = Math.Atan2(tangent.Y, tangent.X);
					Point point2 = new Point(bezierSegment1.Point2.X + Math.Sin(angle) * distanceFromLine, bezierSegment1.Point2.Y - Math.Cos(angle) * distanceFromLine);
					segment = new BezierSegment(point1, point2, end, true);
					newFigure.Segments.Add(segment);
				}
				lastPoint = currentPoint;
			}
			lastPoint = backwardFigure.StartPoint;
			currentPoint = new Point(0, 0);
			helper = new PathFigureHelper(backwardFigure);
			currentDistance = 0;
			for (int i = 0; i < backwardFigure.Segments.Count; i++) {
				LineSegment lineSegment1 = null;
				BezierSegment bezierSegment1 = null;
				LineSegment lineSegment2 = null;
				BezierSegment bezierSegment2 = null;
				CubicBezierCurveHelper bezierHelper1 = null;
				CubicBezierCurveHelper bezierHelper2 = null;
				lineSegment1 = backwardFigure.Segments[i] as LineSegment;
				bezierSegment1 = backwardFigure.Segments[i] as BezierSegment;
				if (i < backwardFigure.Segments.Count - 1) {
					lineSegment2 = backwardFigure.Segments[i + 1] as LineSegment;
					bezierSegment2 = backwardFigure.Segments[i + 1] as BezierSegment;
				}
				Vector vector1 = new Vector(0, 0);
				Vector vector2 = new Vector(0, 0);
				double angle1 = 0;
				double angle2 = 0;
				double averageAngle = 0;
				double differenceAverageAngle = 0;
				double distanceFromLine = width / 2;
				double currentLength = 0;
				if (lineSegment1 != null) {
					vector1 = Point.Subtract(lineSegment1.Point, lastPoint);
					currentPoint = lineSegment1.Point;
					currentLength = vector1.Length;
				}
				if (bezierSegment1 != null) {
					bezierHelper1 = new CubicBezierCurveHelper(lastPoint, bezierSegment1.Point1, bezierSegment1.Point2, bezierSegment1.Point3);
					vector1 = bezierHelper1.GetDerivativeAtFractionLength(1);
					currentPoint = bezierSegment1.Point3;
					currentLength = bezierHelper1.GetLength();
				}
				currentDistance += currentLength;
				if (currentDistance < endPointLength) {
					distanceFromLine *= currentDistance / endPointLength;
				} else if (currentDistance > totalLength - startPointLength) {
					distanceFromLine *= (totalLength - currentDistance) / startPointLength;
				}
				if (lineSegment2 != null) {
					vector2 = Point.Subtract(lineSegment2.Point, currentPoint);
				}
				if (bezierSegment2 != null) {
					bezierHelper2 = new CubicBezierCurveHelper(currentPoint, bezierSegment2.Point1, bezierSegment2.Point2, bezierSegment2.Point3);
					vector2 = bezierHelper2.GetDerivativeAtFractionLength(0);
				}
				if (vector1.Length > 0) {
					angle1 = Math.Atan2(vector1.Y, vector1.X);
				}
				if (vector2.Length > 0) {
					angle2 = Math.Atan2(vector2.Y, vector2.X);
				}
				if (vector1.Length > 0 && vector2.Length > 0) {
					averageAngle = (angle1 + angle2) / 2;
					differenceAverageAngle = (angle1 - angle2) / 2;
				} else if (vector1.Length > 0) {
					averageAngle = angle1;
				} else if (vector2.Length > 0) {
					averageAngle = angle2;
				}
				double cosAngle = Math.Cos(differenceAverageAngle);
				if (Math.Abs(cosAngle) < 0.01) {
					cosAngle = Math.Sign(differenceAverageAngle) * 0.01;
				}
				Point end = new Point(currentPoint.X + Math.Sin(averageAngle) * distanceFromLine / cosAngle, currentPoint.Y - Math.Cos(averageAngle) * distanceFromLine / cosAngle);
				if (lineSegment1 != null) {
					LineSegment segment;
					segment = new LineSegment(end, true);
					newFigure.Segments.Add(segment);
				}
				if (bezierSegment1 != null) {
					BezierSegment segment;
					Vector tangent;
					double angle;
					tangent = bezierHelper1.GetDerivativeAtFractionLength(1.0 / 3.0);
					angle = Math.Atan2(tangent.Y, tangent.X);
					Point point1 = new Point(bezierSegment1.Point1.X + Math.Sin(angle) * distanceFromLine, bezierSegment1.Point1.Y - Math.Cos(angle) * distanceFromLine);
					tangent = bezierHelper1.GetDerivativeAtFractionLength(2.0 / 3.0);
					angle = Math.Atan2(tangent.Y, tangent.X);
					Point point2 = new Point(bezierSegment1.Point2.X + Math.Sin(angle) * distanceFromLine, bezierSegment1.Point2.Y - Math.Cos(angle) * distanceFromLine);
					segment = new BezierSegment(point1, point2, end, true);
					newFigure.Segments.Add(segment);
				}
				lastPoint = currentPoint;
			}
			return newFigure;
		}*/
		
				protected static PathFigure GetPathData(TCord[] cords) {
			if (cords.Length == 0) {
				return null;
			}
			PathFigure pathFigure = new PathFigure();
			PathSegmentCollection pathSegmentCollection = new PathSegmentCollection();
			pathFigure.Segments = pathSegmentCollection;
			pathFigure.StartPoint = new Point(GetLength(cords[0].XPos), -GetLength(cords[0].YPos));
			for (int i = 1; i < cords.Length; i++) {
				if (cords[i].IsFirstCurvePoint) {
					if (i >= cords.Length - 2) {
						break;
					}
					BezierSegment bezierSegment = new BezierSegment(new Point(GetLength(cords[i].XPos), -GetLength(cords[i].YPos)), new Point(GetLength(cords[i + 1].XPos), -GetLength(cords[i + 1].YPos)), new Point(GetLength(cords[i + 2].XPos), -GetLength(cords[i + 2].YPos)), true);
					pathSegmentCollection.Add(bezierSegment);
					i += 2;
				} else {
					LineSegment lineSegment = new LineSegment();
					lineSegment.Point = new Point(GetLength(cords[i].XPos), -GetLength(cords[i].YPos));
					pathSegmentCollection.Add(lineSegment);
				}
			}
			return pathFigure;
		}

		protected static List<PathFigure> GetPathDataList(TCord[] cords) {
			List<PathFigure> pathFigures = new List<PathFigure>();
			if (cords.Length == 0) {
				return pathFigures;
			}
			PathFigure pathFigure = new PathFigure();
			PathSegmentCollection pathSegmentCollection = new PathSegmentCollection();
			pathFigure.Segments = pathSegmentCollection;
			pathFigure.StartPoint = cords[0].GetPoint();
			pathFigures.Add(pathFigure);
			for (int i = 1; i < cords.Length; i++) {
				if (cords[i].IsFirstCurvePoint) {
					if (i >= cords.Length - 2) {
						break;
					}
					BezierSegment bezierSegment = new BezierSegment(new Point(GetLength(cords[i].XPos), -GetLength(cords[i].YPos)), new Point(GetLength(cords[i + 1].XPos), -GetLength(cords[i + 1].YPos)), new Point(GetLength(cords[i + 2].XPos), -GetLength(cords[i + 2].YPos)), true);
					pathSegmentCollection.Add(bezierSegment);
					i += 2;
				} else {
					LineSegment lineSegment = new LineSegment();
					lineSegment.Point = new Point(GetLength(cords[i].XPos), -GetLength(cords[i].YPos));
					pathSegmentCollection.Add(lineSegment);
				}
				if (cords[i].IsCornerPoint && i<cords.Length-1) {
					pathFigure = new PathFigure();
					pathSegmentCollection = new PathSegmentCollection();
					pathFigure.Segments = pathSegmentCollection;
					pathFigure.StartPoint = cords[i].GetPoint();
					pathFigures.Add(pathFigure);
				}
			}
			return pathFigures;
		}
		
		
				/*protected class CubicBezierCurveHelper {

			public Point Start;
			public Point Control1;
			public Point Control2;
			public Point End;

			private Vector startVector {
				get {
					return new Vector(Start.X, Start.Y);
				}
			}
			private Vector control1Vector {
				get {
					return new Vector(Control1.X, Control1.Y);
				}
			}
			private Vector control2Vector {
				get {
					return new Vector(Control2.X, Control2.Y);
				}
			}
			private Vector endVector {
				get {
					return new Vector(End.X, End.Y);
				}
			}

			public CubicBezierCurveHelper() {
			}

			public CubicBezierCurveHelper(Point start, Point control1, Point control2, Point end) {
				Start = start;
				Control1 = control1;
				Control2 = control2;
				End = end;
			}

			public Point GetPointAtFractionLength(double fraction) {
				double t = fraction;
				if (t < 0) {
					return Start;
				}
				if (t > 1) {
					return End;
				}
				Vector vector = Vector.Multiply(Math.Pow(1 - t, 3), startVector) + Vector.Multiply(3 * Math.Pow(1 - t, 2) * t, control1Vector) + Vector.Multiply(3 * Math.Pow(t, 2) * (1 - t), control2Vector) + Vector.Multiply(Math.Pow(t, 3), endVector);
				return new Point(vector.X, vector.Y);
			}

			public double GetLength() {
				int numIntervals = (int)Math.Min(200, Math.Max(10, Point.Subtract(Start, End).Length / 10));
				double length = 0;
				double width = 1.0 / ((double)numIntervals);
				Point point = Start;
				for (int i = 1; i <= numIntervals; i++) {
					Point newPoint = GetPointAtFractionLength(i * width);
					length += Point.Subtract(point, newPoint).Length;
					point = newPoint;
				}
				return length;
			}

			public Vector GetDerivativeAtFractionLength(double fraction) {
				return GetDerivative(fraction);
			}

			private Vector GetDerivative(double t) {
				Vector derivative = new Vector(0, 0);
				derivative = Vector.Multiply(-3 * Math.Pow(1 - t, 2), startVector) + Vector.Multiply(-6 * (1 - t) * t + 3 * Math.Pow(1 - t, 2), control1Vector) + Vector.Multiply(6 * (1 - t) * t - 3 * Math.Pow(t, 2), control2Vector) + Vector.Multiply(3 * Math.Pow(t, 2), endVector);
				return derivative;
			}

		}

		protected class PathFigureHelper {

			private PathFigure pathFigure;
			private double distance;
			private double totalLength;
			private Point lastPoint;
			private int segmentNum;
			double lastPointDistance;
			double lastPointFraction;

			public PathFigureHelper(PathFigure pathFigure) {
				distance = 0;
				totalLength = 0;
				segmentNum = 0;
				this.pathFigure = pathFigure;
				totalLength = GetLengthHelper();
				lastPoint = pathFigure.StartPoint;
				lastPointDistance = 0;
				lastPointFraction = 0;
			}

			private double GetLengthHelper() {
				double length = 0;
				Point lastPoint = pathFigure.StartPoint;
				for (int i = 0; i < pathFigure.Segments.Count; i++) {
					LineSegment lineSegment = pathFigure.Segments[i] as LineSegment;
					BezierSegment bezierSegment = pathFigure.Segments[i] as BezierSegment;
					if (lineSegment != null) {
						Vector vector = Point.Subtract(lineSegment.Point, lastPoint);
						length += vector.Length;
						lastPoint = lineSegment.Point;
					} else if (bezierSegment != null) {
						CubicBezierCurveHelper helper = new CubicBezierCurveHelper(lastPoint, bezierSegment.Point1, bezierSegment.Point2, bezierSegment.Point3);
						length += helper.GetLength();
						lastPoint = bezierSegment.Point3;
					}
				}
				return length;
			}

			public double GetLength() {
				return totalLength;
			}

			public Point GetCurrentPoint() {
				PathSegment segment = pathFigure.Segments[segmentNum];
				LineSegment lineSegment = segment as LineSegment;
				BezierSegment bezierSegment = segment as BezierSegment;
				if (lineSegment != null) {
					Vector vector = Point.Subtract(lineSegment.Point, lastPoint);
					return new Point(lastPoint.X + vector.X * lastPointFraction, lastPoint.Y + vector.Y * lastPointFraction);
				} else if (bezierSegment != null) {
					CubicBezierCurveHelper helper = new CubicBezierCurveHelper(lastPoint, bezierSegment.Point1, bezierSegment.Point2, bezierSegment.Point3);
					return helper.GetPointAtFractionLength(lastPointFraction);
				}
				return new Point(0, 0);
			}

			public PathSegment GetCurrentSegment() {
				return pathFigure.Segments[segmentNum];
			}

			public int GetCurrentSegmentIndex() {
				return segmentNum;
			}

			public Vector GetTangent() {
				PathSegment segment = pathFigure.Segments[segmentNum];
				LineSegment lineSegment = segment as LineSegment;
				BezierSegment bezierSegment = segment as BezierSegment;
				if (lineSegment != null) {
					Vector vector = Point.Subtract(lineSegment.Point, lastPoint);
					return vector;
				} else if (bezierSegment != null) {
					CubicBezierCurveHelper helper = new CubicBezierCurveHelper(lastPoint, bezierSegment.Point1, bezierSegment.Point2, bezierSegment.Point3);
					return helper.GetDerivativeAtFractionLength(lastPointFraction);
				}
				return new Vector(0, 0);
			}

			private double GetLength(PathSegment segment, Point lastPoint) {
				double length = 0;
				LineSegment lineSegment = segment as LineSegment;
				BezierSegment bezierSegment = segment as BezierSegment;
				if (lineSegment != null) {
					Vector vector = Point.Subtract(lineSegment.Point, lastPoint);
					length = vector.Length;
					lastPoint = lineSegment.Point;
				} else if (bezierSegment != null) {
					CubicBezierCurveHelper helper = new CubicBezierCurveHelper(lastPoint, bezierSegment.Point1, bezierSegment.Point2, bezierSegment.Point3);
					length = helper.GetLength();
					lastPoint = bezierSegment.Point3;
				}
				return length;
			}

			public void Reset() {
				distance = 0;
				totalLength = 0;
				segmentNum = 0;
				lastPoint = pathFigure.StartPoint;
				lastPointDistance = 0;
				lastPointFraction = 0;
			}

			public bool AdvanceTo(double distance) {
				Reset();
				return Advance(distance);
			}

			public bool Advance(double distance) {
				PathSegment segment = pathFigure.Segments[segmentNum];
				LineSegment lineSegment = segment as LineSegment;
				BezierSegment bezierSegment = segment as BezierSegment;
				double newLastPointDistance = lastPointDistance + distance;
				double segmentLength = GetLength(segment, lastPoint);
				Point newLastPoint = lastPoint;
				int newSegmentNum = segmentNum;
				while (newLastPointDistance > segmentLength || (newLastPointDistance == segmentLength && newSegmentNum < pathFigure.Segments.Count - 1)) {
					newSegmentNum++;
					if (newSegmentNum >= pathFigure.Segments.Count) {
						return false;
					}
					if (lineSegment != null) {
						newLastPoint = lineSegment.Point;
					}
					if (bezierSegment != null) {
						newLastPoint = bezierSegment.Point3;
					}
					newLastPointDistance -= segmentLength;
					segment = pathFigure.Segments[newSegmentNum];
					lineSegment = segment as LineSegment;
					bezierSegment = segment as BezierSegment;
					segmentLength = GetLength(segment, newLastPoint);
				}
				while (newLastPointDistance < 0) {
					newSegmentNum--;
					if (newSegmentNum < 0) {
						return false;
					}
					segment = pathFigure.Segments[newSegmentNum];
					if (newSegmentNum > 0) {
						PathSegment prevSegment = pathFigure.Segments[newSegmentNum - 1];
						LineSegment prevLineSegment = prevSegment as LineSegment;
						BezierSegment prevBezierSegment = prevSegment as BezierSegment;
						if (prevLineSegment != null) {
							newLastPoint = prevLineSegment.Point;
						}
						if (prevBezierSegment != null) {
							newLastPoint = prevBezierSegment.Point3;
						}
					} else {
						newLastPoint = pathFigure.StartPoint;
					}
					segmentLength = GetLength(segment, newLastPoint);
					newLastPointDistance += segmentLength;
				}
				segmentNum = newSegmentNum;
				lastPoint = newLastPoint;
				this.distance += distance;
				lastPointDistance = newLastPointDistance;
				if (segmentLength == 0) {
					lastPointFraction = 0;
				} else {
					lastPointFraction = newLastPointDistance / segmentLength;
				}
				return true;
			}

			public double GetDistance() {
				return distance;
			}

		}

		protected class CoordinateHelper {

			TCord[] cords;

			public CoordinateHelper(TCord[] cords) {
				this.cords = cords;
			}

			public Vector GetRightDerivativeAtPoint(int num) {
				if (num < cords.Length - 1) {
					if (cords[num + 1].IsFirstCurvePoint) {
						if (num >= cords.Length - 3) {
							return new Vector(0, 0);
						}
						CubicBezierCurveHelper helper = new CubicBezierCurveHelper(cords[num].GetPoint(), cords[num + 1].GetPoint(), cords[num + 2].GetPoint(), cords[num + 3].GetPoint());
						return helper.GetDerivativeAtFractionLength(0);
					} else {
						Vector vector = Point.Subtract(cords[num + 1].GetPoint(), cords[num].GetPoint());
						return vector;
					}
				} else {
					if (cords.Length < 2) {
						return new Vector(0, 0);
					} else {
						Vector vector = Point.Subtract(cords[num].GetPoint(), cords[num - 1].GetPoint());
						return vector;
					}
				}
			}

			public Vector GetLeftDerivativeAtPoint(int num) {
				if (num > 0) {
					if (num >= 3) {
						if (cords[num - 2].IsFirstCurvePoint) {
							CubicBezierCurveHelper helper = new CubicBezierCurveHelper(cords[num - 3].GetPoint(), cords[num - 2].GetPoint(), cords[num - 1].GetPoint(), cords[num].GetPoint());
							return helper.GetDerivativeAtFractionLength(1);
						}
					}

					Vector vector = Point.Subtract(cords[num].GetPoint(), cords[num - 1].GetPoint());
					return vector;
				} else {
					if (cords.Length < 2) {
						return new Vector(0, 0);
					} else {
						Vector vector = Point.Subtract(cords[num + 1].GetPoint(), cords[num].GetPoint());
						return vector;
					}
				}
			}

		}*/
		
		
		/*
				double mainLength = GetLength(lineSymbol.MainLength);
				PathFigure pathFigure = GetPathData(element.Poly);
				PathFigureHelper pathHelper = new PathFigureHelper(pathFigure);
				double totalLength = pathHelper.GetLength();
				if (lineSymbol.MainSymbol.Length > 0) {
					double endLength = 0;
					double midLength = 0;
					int num = 0;
					if (mainLength > 0) {
						endLength = GetLength(lineSymbol.EndLength);
						midLength = totalLength - endLength * 2;
						if (midLength <= 0) {
							endLength = totalLength / 2;
							num = 1;
						} else {
							num = (int)Math.Round(midLength / mainLength + 0.1);//
							if (num > 0) {
								double frac = endLength / mainLength;
								mainLength = totalLength / (2 * frac + num) - 0.0001;//
								endLength = frac * mainLength;
							}
						}
					} else {
						num = 1;
					}
					if (endLength > 0) {
						pathHelper.Advance(endLength);
					}
					int numSymbols = 0;
					do {
						if (lineSymbol.nPrimSym > 1) {
							if ((lineSymbol.nPrimSym - 1) * GetLength(lineSymbol.PrimSymDist) + pathHelper.GetDistance() > totalLength) {
								break;
							}
						}
						for (int k = 0; k < lineSymbol.nPrimSym; k++) {
							if (k > 0) {
								pathHelper.Advance(GetLength(lineSymbol.PrimSymDist));
							}
							Point newPoint;
							Vector newTangent;
							double angle = 0;
							newPoint = pathHelper.GetCurrentPoint();
							newTangent = pathHelper.GetTangent();
							angle = Math.Atan2(newTangent.Y, newTangent.X) / Math.PI * 180.0;
							FrameworkElement mainSymbol;
							mainSymbol = CreateElementsGroup(lineSymbol.MainSymbol);
							Transform transform = new RotateTransform(angle);
							mainSymbol.LayoutTransform = transform;
							Rect temp = GetExtent(lineSymbol.MainSymbol);
							temp.Transform(transform.Value);
							temp.Offset(newPoint.X, newPoint.Y);
							rect = Rect.Union(rect, temp);
							Canvas.SetLeft(mainSymbol, newPoint.X);
							Canvas.SetTop(mainSymbol, newPoint.Y);
							Canvas.SetZIndex(mainSymbol, GetColorDepth(GetMainColorNum(lineSymbol.MainSymbol)));
							parent.Children.Add(mainSymbol);
						}
						if (lineSymbol.nPrimSym > 1) {
							pathHelper.Advance(-GetLength(lineSymbol.PrimSymDist) * (lineSymbol.nPrimSym - 1));
						}
						numSymbols++;
					} while (pathHelper.Advance(mainLength) && numSymbols <= num);
				}
				if (lineSymbol.CornerSymbol.Length > 0) {
					CoordinateHelper helper = new CoordinateHelper(element.Poly);
					for (int i = 0; i < element.Poly.Length; i++) {
						if (element.Poly[i].IsCornerPoint) {
							Point newPoint;
							Vector newTangent1;
							Vector newTangent2;
							double angle1 = 0;
							double angle2 = 0;
							newPoint = element.Poly[i].GetPoint();
							newTangent1 = helper.GetLeftDerivativeAtPoint(i);
							newTangent2 = helper.GetRightDerivativeAtPoint(i);
							angle1 = Math.Atan2(newTangent1.Y, newTangent1.X) / Math.PI * 180.0;
							angle2 = Math.Atan2(newTangent2.Y, newTangent2.X) / Math.PI * 180.0;
							FrameworkElement cornerSymbol;
							cornerSymbol = CreateElementsGroup(lineSymbol.CornerSymbol);
							Transform transform = new RotateTransform((angle1 + angle2) / 2);
							cornerSymbol.LayoutTransform = transform;
							Rect temp = GetExtent(lineSymbol.CornerSymbol);
							temp.Transform(transform.Value);
							temp.Offset(newPoint.X, newPoint.Y);
							rect = Rect.Union(rect, temp);
							Canvas.SetLeft(cornerSymbol, newPoint.X);
							Canvas.SetTop(cornerSymbol, newPoint.Y);
							Canvas.SetZIndex(cornerSymbol, GetColorDepth(GetMainColorNum(lineSymbol.CornerSymbol)));
							parent.Children.Add(cornerSymbol);
						}
					}
				}
				if (lineSymbol.EndSymbol.Length > 0 && element.Poly.Length > 0) {
					CoordinateHelper helper = new CoordinateHelper(element.Poly);
					int num = element.Poly.Length - 1;
					Point newPoint;
					Vector newTangent;
					double angle = 0;
					newPoint = element.Poly[num].GetPoint();
					newTangent = helper.GetLeftDerivativeAtPoint(num);
					angle = Math.Atan2(newTangent.Y, newTangent.X) / Math.PI * 180.0;
					FrameworkElement endSymbol;
					endSymbol = CreateElementsGroup(lineSymbol.EndSymbol);
					Transform transform = new RotateTransform(angle);
					endSymbol.LayoutTransform = transform;
					Rect temp = GetExtent(lineSymbol.EndSymbol);
					temp.Transform(transform.Value);
					temp.Offset(newPoint.X, newPoint.Y);
					rect = Rect.Union(rect, temp);
					Canvas.SetLeft(endSymbol, newPoint.X);
					Canvas.SetTop(endSymbol, newPoint.Y);
					Canvas.SetZIndex(endSymbol, GetColorDepth(GetMainColorNum(lineSymbol.EndSymbol)));
					parent.Children.Add(endSymbol);
				}
				if (lineSymbol.LineWidth > 0) {
					if (lineSymbol.MainGap > 0 && lineSymbol.SecGap == 0 && lineSymbol.MainSymbol.Length == 0) {
						List<PathFigure> pathFigures = GetPathDataList(element.Poly);
						if (pathFigures.Count == 0) {
							return true;
						}
						for (int i = 0; i < pathFigures.Count; i++) {
							pathFigure = pathFigures[i];
							pathHelper = new PathFigureHelper(pathFigure);
							totalLength = pathHelper.GetLength();
							System.Windows.Shapes.Path path = new System.Windows.Shapes.Path();
							path.Stroke = new SolidColorBrush(GetColor(lineSymbol.LineColor));
							path.StrokeThickness = GetLength(lineSymbol.LineWidth);
							PathGeometry geometry = new PathGeometry(new PathFigureCollection(new PathFigure[] { pathFigure }));
							path.Data = geometry;
							mainLength = GetLength(lineSymbol.MainLength);
							double gapLength = GetLength(lineSymbol.MainGap);
							int num = (int)Math.Round((totalLength + gapLength) / (mainLength + gapLength) + 0.1);//
							if (num > 0) {
								num = (int)Math.Max(2, num);
								double frac = gapLength / mainLength;
								double wholeMainLength = (totalLength + gapLength) / num - 0.0001;//
								mainLength = wholeMainLength / (frac + 1.0);
								gapLength = mainLength * frac;
							}
							path.StrokeDashArray = new DoubleCollection(new double[] { mainLength / GetLength(lineSymbol.LineWidth), gapLength / GetLength(lineSymbol.LineWidth) });
							Canvas.SetZIndex(path, GetColorDepth(lineSymbol.LineColor));
							parent.Children.Add(path);
							Pen pen = new Pen(Brushes.Black, GetLength(lineSymbol.LineWidth));
							rect = Rect.Union(rect, geometry.GetRenderBounds(pen));
						}
					} else {
						pathFigure = GetPathData(element.Poly);
						System.Windows.Shapes.Path path = new System.Windows.Shapes.Path();
						if (lineSymbol.LineEnds != 0 && (lineSymbol.DistFromStart != 0 || lineSymbol.DistToEnd != 0) && lineSymbol.MainGap == 0 && lineSymbol.SecGap == 0) {
							pathFigure = GetPointedPath(element.Poly, GetLength(lineSymbol.LineWidth), GetLength(lineSymbol.DistFromStart), GetLength(lineSymbol.DistToEnd));
							path.Fill = new SolidColorBrush(GetColor(lineSymbol.LineColor));
						} else {
							path.Stroke = new SolidColorBrush(GetColor(lineSymbol.LineColor));
							path.StrokeThickness = GetLength(lineSymbol.LineWidth);
						}
						PathGeometry geometry = new PathGeometry(new PathFigureCollection(new PathFigure[] { pathFigure }));
						path.Data = geometry;
						if (lineSymbol.MainGap > 0) {
							if (lineSymbol.SecGap > 0) {
								double firstLength = 0.5 * (mainLength - GetLength(lineSymbol.SecGap));
								double firstGapLength = GetLength(lineSymbol.SecGap);
								double secondGapLength = GetLength(lineSymbol.MainGap);
								double wholeMainLength = firstLength * 2 + firstGapLength + secondGapLength;
								if (lineSymbol.MainSymbol.Length == 0) {
									int num = (int)Math.Round((totalLength + secondGapLength) / (wholeMainLength) + 0.1);//
									if (num > 0) {
										num = (int)Math.Max(2, num);
										double firstLengthFrac = firstLength / wholeMainLength;
										double firstGapFrac = firstGapLength / wholeMainLength;
										double secondGapFrac = secondGapLength / wholeMainLength;
										wholeMainLength = (totalLength + secondGapLength) / num - 0.0001;//
										firstLength = wholeMainLength * firstLengthFrac;
										firstGapLength = wholeMainLength * firstGapFrac;
										secondGapLength = wholeMainLength * secondGapFrac;
									}
								}
								path.StrokeDashArray = new DoubleCollection(new double[] { firstLength / GetLength(lineSymbol.LineWidth), firstGapLength / GetLength(lineSymbol.LineWidth), firstLength / GetLength(lineSymbol.LineWidth), secondGapLength / GetLength(lineSymbol.LineWidth) });
							} else {
								double gapLength = GetLength(lineSymbol.MainGap);
								if (lineSymbol.MainSymbol.Length == 0) {
									int num = (int)Math.Round((totalLength + gapLength) / (mainLength + gapLength) + 0.1);//
									if (num > 0) {
										num = (int)Math.Max(2, num);
										double frac = gapLength / mainLength;
										double wholeMainLength = (totalLength + gapLength) / num - 0.0001;//
										mainLength = wholeMainLength / (frac + 1.0);
										gapLength = mainLength * frac;
									}
								}
								path.StrokeDashArray = new DoubleCollection(new double[] { mainLength / GetLength(lineSymbol.LineWidth), gapLength / GetLength(lineSymbol.LineWidth) });
							}
						} else {
							if (lineSymbol.SecGap > 0) {
								path.StrokeDashArray = new DoubleCollection(new double[] { (mainLength - GetLength(lineSymbol.SecGap)) / GetLength(lineSymbol.LineWidth), GetLength(lineSymbol.SecGap) / GetLength(lineSymbol.LineWidth) });
							}
						}
						Canvas.SetZIndex(path, GetColorDepth(lineSymbol.LineColor));
						parent.Children.Add(path);
						Pen pen = new Pen(Brushes.Black, GetLength(lineSymbol.LineWidth));
						rect = Rect.Union(rect, geometry.GetRenderBounds(pen));
					}
				}
				if (lineSymbol.DblMode != 0) {
					pathFigure = GetPathData(element.Poly);
					PathGeometry geometry = new PathGeometry(new PathFigureCollection(new PathFigure[] { pathFigure }));
					if (lineSymbol.DblFlags != 0) {
						System.Windows.Shapes.Path path = new System.Windows.Shapes.Path();
						path.Stroke = new SolidColorBrush(GetColor(lineSymbol.DblFillColor));
						path.StrokeThickness = GetLength(lineSymbol.DblWidth);
						path.Data = geometry;
						Canvas.SetZIndex(path, GetColorDepth(lineSymbol.DblFillColor));
						parent.Children.Add(path);
						Pen pen = new Pen(Brushes.Black, GetLength(lineSymbol.LineWidth));
						rect = Rect.Union(rect, geometry.GetRenderBounds(pen));
					}
					if (lineSymbol.DblLeftWidth > 0) {
						PathFigure newFigure = GetShiftedPath(pathFigure, GetLength(lineSymbol.DblWidth / 2));
						PathGeometry newGeometry = new PathGeometry(new PathFigureCollection(new PathFigure[] { newFigure }));
						System.Windows.Shapes.Path path = new System.Windows.Shapes.Path();
						path.Stroke = new SolidColorBrush(GetColor(lineSymbol.DblLeftColor));
						path.StrokeThickness = GetLength(lineSymbol.DblLeftWidth);
						path.Data = newGeometry;
						Canvas.SetZIndex(path, GetColorDepth(lineSymbol.DblLeftColor));
						parent.Children.Add(path);
						Pen pen = new Pen(Brushes.Black, GetLength(lineSymbol.LineWidth));
						rect = Rect.Union(rect, geometry.GetRenderBounds(pen));
					}
					if (lineSymbol.DblRightWidth > 0) {
						PathFigure newFigure = GetShiftedPath(pathFigure, -GetLength(lineSymbol.DblWidth / 2));
						PathGeometry newGeometry = new PathGeometry(new PathFigureCollection(new PathFigure[] { newFigure }));
						System.Windows.Shapes.Path path = new System.Windows.Shapes.Path();
						path.Stroke = new SolidColorBrush(GetColor(lineSymbol.DblRightColor));
						path.StrokeThickness = GetLength(lineSymbol.DblRightWidth);
						path.Data = newGeometry;
						Canvas.SetZIndex(path, GetColorDepth(lineSymbol.DblRightColor));
						parent.Children.Add(path);
						Pen pen = new Pen(Brushes.Black, GetLength(lineSymbol.LineWidth));
						rect = Rect.Union(rect, geometry.GetRenderBounds(pen));
					}
				}*/
				
				
				/*TTextSym textSymbol = (TTextSym)symbol;
				TextBlock textBlock = new TextBlock();
				textBlock.Foreground = new SolidColorBrush(GetColor(textSymbol.FontColor));
				double fontSize = ((double)textSymbol.FontSize) / 10.0 * 96.0 / 72.0;
				textBlock.FontSize = fontSize;
				string text = element.ExtraString;
				if (text.StartsWith("\r")) {
					text = text.Substring(1);
				}
				if (text.StartsWith("\n")) {
					text = text.Substring(1);
				}
				text = ReplaceTabs(text, textSymbol.Tabs, fontSize);
				textBlock.Text = text;
				textBlock.FontFamily = new FontFamily(textSymbol.FontName);
				if (textSymbol.Italic == true) {
					textBlock.FontStyle = FontStyles.Italic;
				}
				textBlock.LineHeight = textSymbol.LineSpace * fontSize / 100.0;
				textBlock.LineStackingStrategy = LineStackingStrategy.BlockLineHeight;
				if (textSymbol.LBOn != 0) {
					textBlock.LineHeight += GetLength(textSymbol.LBWidth);
					textBlock.LineHeight += GetLength(textSymbol.LBDist);
				}
				if (textSymbol.ParaSpace > 0) {
					textBlock.LineHeight += GetLength(textSymbol.ParaSpace);
				}
				if (textSymbol.Weight == 700) {
					textBlock.FontWeight = FontWeights.Bold;
				}
				if (element.Poly.Length <= 0) {
					return false;
				}
				Rect textRect;
				if (element.Poly.Length == 4) {
					double x = GetLength(element.Poly[3].XPos);
					double y = GetLength(element.Poly[3].YPos); ;
					double width = GetLength(element.Poly[1].XPos - element.Poly[0].XPos);
					double height = GetLength(element.Poly[2].YPos - element.Poly[1].YPos);
					if (width < 0) {
						x -= width;
						width = -width;
					}
					if (height < 0) {
						y -= height;
						height = -height;
					}
					textBlock.Width = width;
					textBlock.Height = height;
					textBlock.TextWrapping = TextWrapping.Wrap;
					textRect = new Rect(x, -y, width, height);
				} else {
					textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
					textRect = new Rect(GetLength(element.Poly[0].XPos), -GetLength(element.Poly[0].YPos) - textBlock.LineHeight * 0.8, textBlock.DesiredSize.Width, textBlock.DesiredSize.Height);
				}
				rect = textRect;
				Canvas.SetZIndex(textBlock, GetColorDepth(textSymbol.FontColor));
				if (textSymbol.Alignment == 1) {
					textBlock.TextAlignment = TextAlignment.Center;
					if (element.Poly.Length != 4) {
						rect.Offset(-textBlock.DesiredSize.Width / 2, 0);
					}
				} else if (textSymbol.Alignment == 2) {
					textBlock.TextAlignment = TextAlignment.Right;
					if (element.Poly.Length != 4) {
						rect.Offset(-textBlock.DesiredSize.Width, 0);
					}
				} else {
					textBlock.TextAlignment = TextAlignment.Left;
				}
				Canvas.SetLeft(textBlock, rect.Left);
				Canvas.SetTop(textBlock, rect.Top);
				if (element.Ang != 0) {
					Transform tranform = new RotateTransform(-((double)element.Ang) * 0.1, 0, textBlock.LineHeight * 0.8);
					textBlock.RenderTransform = tranform;
					tranform = new RotateTransform(-((double)element.Ang) * 0.1, rect.Left, rect.Top+textBlock.LineHeight * 0.8);
					rect.Transform(tranform.Value);
				}
				parent.Children.Add(textBlock);
				return true;*/
				
						protected string ReplaceTabs(string text, int[] tabs, double fontSize) {
			if (fontSize <= 0 || tabs.Length==0) {
				return text.Replace("\t", "");
			}
			if (text.IndexOf("\t") < 0) {
				return text;
			}
			TextBlock tb = new TextBlock();
			tb.Text = " ";
			tb.FontSize = fontSize;
			tb.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
			double size = tb.DesiredSize.Width;
			double textSize;
			string newText = "";
			string currentLine = "";
			int lineBreakPos = 0;
			int lastLineBreakPos = 0;
			while (lastLineBreakPos < text.Length) {
				lineBreakPos = text.IndexOf("\n", lastLineBreakPos);
				if (lineBreakPos < 0) {
					currentLine = text.Substring(lastLineBreakPos);
					lastLineBreakPos = text.Length;
				} else {
					currentLine = text.Substring(lastLineBreakPos, lineBreakPos + 1 - lastLineBreakPos);
					lastLineBreakPos = lineBreakPos + 1;
				}
				int pos = 0;
				int lastPos = 0;
				int i = 0;
				while(true) {
					int numSpaces = 0;
					pos = currentLine.IndexOf("\t", lastPos);
					if (pos < 0) {
						break;
					}
					string str = "";
					if (pos > lastPos) {
						str = currentLine.Substring(lastPos, pos - lastPos);
					}
					tb.Text = str;
					tb.FontSize = fontSize;
					tb.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
					textSize = tb.DesiredSize.Width;
					double remainingDist;
					if (i > 0) {
						remainingDist = GetLength(tabs[i] - tabs[i - 1]);
					} else {
						remainingDist = GetLength(tabs[i]);
					}
					remainingDist -= textSize;
					while (remainingDist < 0) {
						i++;
						if (i >= tabs.Length) {
							i = tabs.Length-1;
						}
						if (i > 0) {
							remainingDist += GetLength(tabs[i] - tabs[i - 1]);
						} else {
							remainingDist += GetLength(tabs[i]);
						}
					}
					if (remainingDist > 0) {
						numSpaces = (int)Math.Max(Math.Floor(remainingDist / size),1);
					}
					if (pos > lastPos) {
						newText += currentLine.Substring(lastPos, pos - lastPos);
					}
					for (int j = 0; j < numSpaces; j++) {
						newText += " ";
					}
					lastPos = pos + 1;
					i++;
					if (i >= tabs.Length) {
						i = tabs.Length-1;
					}
				}
				if (lastPos < currentLine.Length) {
					newText += currentLine.Substring(lastPos);
				}
			}
			newText = newText.Replace("\t", "");
			return newText;
		}
		
		
		
		using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
using Microsoft.Win32;
using System.IO;
using System.IO.Packaging;
using System.Printing;
using System.Windows.Markup;
using System.Threading;
using System.Xml;

namespace OPlanner {

	public partial class PrintPreview : Window {

		private PrintDialog printDialog;
		private FixedDocument fixedDoc;
		private string printName;
		private bool printViaImage;

		public PrintPreview() {
			InitializeComponent();
			printName = "OPlanner Document";
			printViaImage = false;
		}

		public bool PrintViaImage {
			get {
				return printViaImage;
			}
			set {
				printViaImage = value;
			}
		}

		public void SetPrintDialog(PrintDialog dialog) {
			printDialog = dialog;
		}

		public void SetFixedDoc(FixedDocument newFixedDoc) {
			fixedDoc = newFixedDoc;
			mainViewer.Document = fixedDoc;
		}

		public void SetPrintName(string newPrintName) {
			printName = newPrintName;
		}

		private FixedDocument GetFixedDoc() {
			if (printViaImage == false) {
				return fixedDoc;
			} else {
				FixedDocument doc = new FixedDocument();
				for (int i = 0; i < fixedDoc.Pages.Count; i++) {
					if (fixedDoc.Pages[i].Child == null) {
						continue;
					}
					FixedPage currentPage = fixedDoc.Pages[i].Child;
					PageContent pageContent = new PageContent();
					FixedPage page = new FixedPage();
					((IAddChild)pageContent).AddChild(page);
					doc.Pages.Add(pageContent);
					currentPage.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
					Size size = currentPage.DesiredSize;
					page.Width = size.Width;
					page.Height = size.Height;
					double dpiX;
					if (printDialog.PrintTicket.PageResolution.X != null) {
						dpiX = printDialog.PrintTicket.PageResolution.X.Value;
					} else {
						dpiX = 600;
					}
					if (dpiX > 600) {
						dpiX = 600;
					}
					double dpiY;
					if (printDialog.PrintTicket.PageResolution.Y != null) {
						dpiY = printDialog.PrintTicket.PageResolution.Y.Value;
					} else {
						dpiY = 600;
					}
					if (dpiY > 600) {
						dpiY = 600;
					}
					RenderTargetBitmap bmp = new RenderTargetBitmap((int)(Math.Ceiling(size.Width * dpiX / 96.0)), (int)(Math.Ceiling(size.Height * dpiY / 96.0)), dpiX, dpiY, PixelFormats.Pbgra32);
					BitmapEncoder encoder;
					encoder = new PngBitmapEncoder();
					Rectangle rect = new Rectangle();
					rect.Width = bmp.Width;
					rect.Height = bmp.Height;
					rect.Fill = Brushes.White;
					rect.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
					rect.Arrange(new Rect(new Point(0, 0), rect.DesiredSize));
					bmp.Render(rect);
					bmp.Render(currentPage);
					encoder.Frames.Add(BitmapFrame.Create(bmp));
					Stream stream = new MemoryStream();
					encoder.Save(stream);
					stream.Seek(0, SeekOrigin.Begin);
					BitmapImage bmpImage = new BitmapImage();
					bmpImage.BeginInit();
					bmpImage.CacheOption = BitmapCacheOption.OnLoad;
					bmpImage.StreamSource = stream;
					bmpImage.EndInit();
					Console.WriteLine(bmpImage.StreamSource);
					Image image = new Image();
					image.Stretch = Stretch.None;
					image.Source = bmpImage;
					stream.Close();
					page.Children.Add(image);
				}
				return doc;
			}
		}

		protected void OnPrint(object sender, EventArgs e) {
			FixedDocument doc = GetFixedDoc();
			PrintQueue queue = printDialog.PrintQueue;
			queue.CurrentJobSettings.Description = printName;
			XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue);
			writer.WriteAsync(doc, printDialog.PrintTicket);
		}
	
	}

}


/*double averageAngle = GetAngleAtStart(true);
				double differenceAverageAngle;
				if (PreviousSegment != null) {
					differenceAverageAngle = (PreviousSegment.GetAngleAtStart(false) - GetAngleAtStart(false)) / 2;
				} else {
					differenceAverageAngle = 0;
				}
				double cosAngle = Math.Cos(differenceAverageAngle);
				if (Math.Abs(cosAngle) < 0.01) {
					cosAngle = Math.Sign(differenceAverageAngle) * 0.01;
				}
				double distanceFromLine = startDistance / cosAngle;
				Point newStart = new Point(Start.X + Math.Sin(averageAngle) * distanceFromLine, Start.Y - Math.Cos(averageAngle) * distanceFromLine);
				//Point newControl1 = new Point(Control1.X + Math.Sin(averageAngle) * distanceFromLine, Control1.Y - Math.Cos(averageAngle) * distanceFromLine);
				averageAngle = GetAngleAtDistance(Length / 3);
				Point newControl1 = new Point(Control1.X + Math.Sin(averageAngle) * distanceFromLine, Control1.Y - Math.Cos(averageAngle) * distanceFromLine);
				averageAngle = GetAngleAtEnd(true);
				if (NextSegment != null) {
					differenceAverageAngle = (GetAngleAtEnd(false) - NextSegment.GetAngleAtStart(false)) / 2;
				} else {
					differenceAverageAngle = 0;
				}
				cosAngle = Math.Cos(differenceAverageAngle);
				if (Math.Abs(cosAngle) < 0.01) {
					cosAngle = Math.Sign(differenceAverageAngle) * 0.01;
				}
				distanceFromLine = endDistance / cosAngle;
				Point newEnd = new Point(End.X + Math.Sin(averageAngle) * distanceFromLine, End.Y - Math.Cos(averageAngle) * distanceFromLine);
				//Point newControl2 = new Point(Control2.X + Math.Sin(averageAngle) * distanceFromLine, Control2.Y - Math.Cos(averageAngle) * distanceFromLine);
				averageAngle = GetAngleAtDistance(Length*2 / 3);
				Point newControl2 = new Point(Control2.X + Math.Sin(averageAngle) * distanceFromLine, Control2.Y - Math.Cos(averageAngle) * distanceFromLine);
				OcdBaseSegment newSegment = Clone(newStart, newControl1, newControl2, newEnd);
				if (startDistance >= 0) {
					newSegment.IsStroked = IsLeftStroked;
				} else {
					newSegment.IsStroked = IsRightStroked;
				}
				return newSegment;*/
				
				
				
				
						/*protected Brush GetHatchBrush(Color hatchColor, double lineThickness, double spacing, double angle) {
			Canvas canvas = new Canvas();
			canvas.Width = spacing + lineThickness;
			canvas.Height = 10;
			Line line = new Line();
			line.Stroke = new SolidColorBrush(hatchColor);
			line.StrokeThickness = lineThickness;
			line.X1 = 0;
			line.Y1 = 0;
			line.X2 = 0;
			line.Y2 = 10;
			Canvas.SetLeft(line, lineThickness / 2);
			canvas.Background = Brushes.Transparent;
			canvas.Children.Add(line);
			VisualBrush brush = new VisualBrush(canvas);
			brush.TileMode = TileMode.Tile;
			brush.Stretch = Stretch.None;
			brush.Viewbox = new Rect(0, 0, spacing + lineThickness, 10);
			brush.Viewport = new Rect(0, 0, spacing + lineThickness, 10);
			brush.ViewboxUnits = BrushMappingMode.Absolute;
			brush.ViewportUnits = BrushMappingMode.Absolute;
			brush.Transform = new RotateTransform(-angle * 0.1);
			return brush;
		}*/
		
		protected Brush GetStandardStructBrush(TSymElt[] elts, double width, double height, double angle) {
			FrameworkElement symbol = CreateElementsGroup(elts);
			if (symbol == null) {
				return Brushes.Transparent;
			}
			Canvas canvas = new Canvas();
			canvas.Width = width * 1.15;
			canvas.Height = height * 1.15;
			canvas.Background = Brushes.Transparent;
			Canvas.SetLeft(symbol, canvas.Width / 2);
			Canvas.SetTop(symbol, canvas.Height / 2);
			canvas.Children.Add(symbol);
			VisualBrush brush = new VisualBrush(canvas);
			brush.TileMode = TileMode.Tile;
			brush.Stretch = Stretch.None;
			brush.Viewbox = new Rect(0, 0, canvas.Width, canvas.Height);
			brush.Viewport = new Rect(0, 0, canvas.Width, canvas.Height);
			brush.ViewboxUnits = BrushMappingMode.Absolute;
			brush.ViewportUnits = BrushMappingMode.Absolute;
			brush.Transform = new RotateTransform(-angle * 0.1);
			return brush;
		}

		protected Brush GetHoneycombStructBrush(TSymElt[] elts, double width, double height, double angle) {
			FrameworkElement symbol = CreateElementsGroup(elts);
			Rect rect = GetExtent(elts);
			if (symbol == null) {
				return Brushes.Transparent;
			}
			Canvas canvas = new Canvas();
			canvas.Width = width;
			canvas.Height = height * 2;
			canvas.Background = Brushes.Transparent;
			Canvas.SetTop(symbol, rect.Height / 2);
			canvas.Children.Add(symbol);
			symbol = CreateElementsGroup(elts);
			Canvas.SetTop(symbol, rect.Height / 2);
			Canvas.SetLeft(symbol, width);
			canvas.Children.Add(symbol);
			symbol = CreateElementsGroup(elts);
			Canvas.SetLeft(symbol, width / 2);
			Canvas.SetTop(symbol, height + rect.Height / 2);
			canvas.Children.Add(symbol);
			VisualBrush brush = new VisualBrush(canvas);
			brush.TileMode = TileMode.Tile;
			brush.Stretch = Stretch.None;
			brush.Viewbox = new Rect(0, 0, width, height * 2);
			brush.Viewport = new Rect(0, 0, width, height * 2);
			brush.ViewboxUnits = BrushMappingMode.Absolute;
			brush.ViewportUnits = BrushMappingMode.Absolute;
			brush.Transform = new RotateTransform(-angle * 0.1);
			return brush;
		}
		
		protected FrameworkElement CreateElementsGroup(TSymElt[] elts) {
			if (elts.Length == 0) {
				return null;
			}
			Canvas parent = new Canvas();
			parent.Background = Brushes.Transparent;
			for (int i = 0; i < elts.Length; i++) {
				UIElement elt = CreateElement(elts[i]);
				if (elt != null) {
					parent.Children.Add(elt);
				}
			}
			return parent;
		}

		protected FrameworkElement CreateElement(TSymElt elt) {
			Color color = GetColor(elt.stColor);
			Brush brush = new SolidColorBrush(color);
			PathFigure pathFigure;
			Geometry geometry;
			System.Windows.Shapes.Path path;
			switch (elt.stType) {
				case 1:
					OcdPathHelper pathHelper = new OcdPathHelper(elt.stPoly);
					pathFigure = pathHelper.GetPathFigure();
					geometry = new PathGeometry(new PathFigureCollection(new PathFigure[] { pathFigure }));
					path = new System.Windows.Shapes.Path();
					path.Stroke = brush;
					path.StrokeThickness = GetLength(elt.stLineWidth);
					path.Data = geometry;
					Canvas.SetZIndex(path, GetColorDepth(elt.stColor));
					return path;
				case 2:
					geometry = GetAreaGeometry(elt.stPoly);
					path = new System.Windows.Shapes.Path();
					path.Fill = brush;
					path.Data = geometry;
					Canvas.SetZIndex(path, GetColorDepth(elt.stColor));
					return path;
				case 3:
					Ellipse circle = new Ellipse();
					circle.Width = GetLength(elt.stDiameter);
					circle.Height = GetLength(elt.stDiameter);
					circle.Stroke = brush;
					circle.StrokeThickness = GetLength(elt.stLineWidth);
					if (elt.stPoly.Length <= 0) {
						return null;
					}
					Canvas.SetLeft(circle, GetLength(elt.stPoly[0].XPos) - circle.Width / 2);
					Canvas.SetTop(circle, -GetLength(elt.stPoly[0].YPos) - circle.Height / 2);
					Canvas.SetZIndex(circle, GetColorDepth(elt.stColor));
					return circle;
				case 4:
					Ellipse dot = new Ellipse();
					dot.Width = GetLength(elt.stDiameter);
					dot.Height = GetLength(elt.stDiameter);
					dot.Fill = brush;
					if (elt.stPoly.Length <= 0) {
						return null;
					}
					Canvas.SetLeft(dot, GetLength(elt.stPoly[0].XPos) - dot.Width / 2);
					Canvas.SetTop(dot, -GetLength(elt.stPoly[0].YPos) - dot.Height / 2);
					Canvas.SetZIndex(dot, GetColorDepth(elt.stColor));
					return dot;
				default:
					return null;
			}
		}
		
							/*brush = GetHatchBrush(GetColor(areaSymbol.HatchColor), GetLength(areaSymbol.HatchLineWidth), GetLength(areaSymbol.HatchDist) - GetLength(areaSymbol.HatchLineWidth), element.Ang + areaSymbol.HatchAngle1 - 90 * 10);//
					path = new System.Windows.Shapes.Path();
					path.Fill = brush;
					path.Data = geometry;
					Canvas.SetZIndex(path, GetColorDepth(areaSymbol.HatchColor));
					parent.Children.Add(path);
					path = new System.Windows.Shapes.Path();
					brush = GetHatchBrush(GetColor(areaSymbol.HatchColor), GetLength(areaSymbol.HatchLineWidth), GetLength(areaSymbol.HatchDist) - GetLength(areaSymbol.HatchLineWidth), element.Ang + areaSymbol.HatchAngle2 - 90 * 10);//
					path.Fill = brush;
					path.Data = geometry;
					Canvas.SetZIndex(path, GetColorDepth(areaSymbol.HatchColor));
					parent.Children.Add(path);*/
					
					brush = GetHoneycombStructBrush(areaSymbol.Elts, GetLength(areaSymbol.StructWidth), GetLength(areaSymbol.StructHeight), areaSymbol.StructAngle);
					path = new System.Windows.Shapes.Path();
					path.Fill = brush;
					path.Data = geometry;
					Canvas.SetZIndex(path, GetColorDepth(GetMainColorNum(areaSymbol.Elts)));
					parent.Children.Add(path);
					
					
							private DescriptionManager descriptionManager;
		public DescriptionManager DescriptionManager {
			get {
				return descriptionManager;
			}
			set {
				descriptionManager = value;
			}
		}
		
		mapBrush = new VisualBrush(mapVisual);
			mapBrush.TileMode = TileMode.None;
			mapBrush.Stretch = Stretch.None;
			
			
					private VisualBrush mapBrush;
		public VisualBrush MapBrush {
			get {
				return mapBrush;
			}
		}