public void testWriteXML() { Sketch.Sketch sketch = new Sketch.Sketch(); sketch.XmlAttrs.Id = System.Guid.NewGuid(); Sketch.Shape shape = new Sketch.Shape(); shape.XmlAttrs.Id = System.Guid.NewGuid(); shape.XmlAttrs.Name = "shapeName"; shape.XmlAttrs.Type = "shape"; shape.XmlAttrs.Time = "111"; Sketch.Stroke stroke; Sketch.Substroke substroke; Sketch.Point point; ulong h; ulong i; ulong j; for (h = 0; h < 3; ++h) { stroke = new Sketch.Stroke(); stroke.XmlAttrs.Id = System.Guid.NewGuid(); stroke.XmlAttrs.Name = "strokeName"; stroke.XmlAttrs.Type = "stroke"; stroke.XmlAttrs.Time = h; for (i = 0; i < 5; ++i) { substroke = new Sketch.Substroke(); substroke.XmlAttrs.Id = System.Guid.NewGuid(); substroke.XmlAttrs.Name = "substrokeName"; substroke.XmlAttrs.Type = "substroke"; substroke.XmlAttrs.Time = i; for (j = 0; j < 10; ++j) { point = new Sketch.Point(); point.XmlAttrs.X = (float)random.NextDouble(); point.XmlAttrs.Y = (float)random.NextDouble(); point.XmlAttrs.Id = System.Guid.NewGuid(); point.XmlAttrs.Pressure = (ushort)(random.NextDouble() * 256); point.XmlAttrs.Name = "point" + j.ToString(); point.XmlAttrs.Time = j; substroke.AddPoint(point); } stroke.AddSubstroke(substroke); shape.AddSubstroke(substroke); } sketch.AddStroke(stroke); } sketch.AddShape(shape); sketch.Strokes[0].SplitStrokeAt(new int[] { 7, 14, 16, 21 }); ConverterXML.MakeXML xml = new ConverterXML.MakeXML(sketch); xml.WriteXML("test.xml"); }
/// <summary> /// Takes an Ink.Stroke and outputs an internal representation that can /// then be output to an XML file /// </summary> /// <param name="inkStroke">Ink.Stroke which will have extracted from it the information necessary to store a Stroke in MIT XML.</param> /// <param name="transf">Transformation matrix to shift the stroke by</param> /// <param name="shift">Boolean for if we should shift by the transformation matrix</param> /// <returns>PointsAndShape object that stores the extracted information.</returns> public static Sketch.Stroke StripStrokeData(Microsoft.Ink.Stroke inkStroke, Matrix transf, bool shift) { int i; int length; // Get the timestamp for the function using an undocumented GUID (Microsoft.Ink.StrokeProperty.TimeID) to // get the time as a byte array, which we then convert to a long ulong theTime; if (inkStroke.ExtendedProperties[Microsoft.Ink.StrokeProperty.TimeID] != null) { byte[] timeBits = inkStroke.ExtendedProperties[Microsoft.Ink.StrokeProperty.TimeID].Data as byte[]; // Filetime format ulong fileTime = BitConverter.ToUInt64(timeBits, 0); // MIT time format theTime = (fileTime - 116444736000000000) / 10000; //string time = theTime.ToString(); } else { theTime = (ulong)System.DateTime.Now.Ticks; } // Grab X and Y int[] xData = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.X); int[] yData = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.Y); if (shift) { // Shift X and Y according to transformation matrix System.Drawing.Point[] pointData = new System.Drawing.Point[xData.Length]; length = xData.Length; for (i = 0; i < length; i++) { pointData[i] = new System.Drawing.Point(xData[i], yData[i]); } transf.TransformPoints(pointData); //Console.WriteLine("x: " + (pointData[0].X - xData[0]) + " y: " + (pointData[0].Y - yData[0])); for (i = 0; i < length; i++) { xData[i] = pointData[i].X; yData[i] = pointData[i].Y; } } Microsoft.Ink.DrawingAttributes drawingAttributes = inkStroke.DrawingAttributes; System.Drawing.Rectangle boundingBox = inkStroke.GetBoundingBox(); // Grab the color int color = drawingAttributes.Color.ToArgb(); // THIS IS DRAWING POINT (PENTIP) HEIGHT AND WIDTH... WE DONT HAVE ANYWHERE TO PUT IT... //string height = inkStroke.DrawingAttributes.Height.ToString(); //string width = inkStroke.DrawingAttributes.Width.ToString(); // Grab height and width of total stroke float height = boundingBox.Height; float width = boundingBox.Width; // Grab penTip string penTip = drawingAttributes.PenTip.ToString(); // Grab raster string raster = drawingAttributes.RasterOperation.ToString(); float x = Convert.ToSingle(boundingBox.X); float y = Convert.ToSingle(boundingBox.Y); //float leftx = Convert.ToSingle(boundingBox.Left); //float topy = Convert.ToSingle(boundingBox.Top); // If the pressure data is included take it, otherwise set to 255/2's int[] pressureData; if (IsPropertyIncluded(inkStroke, Microsoft.Ink.PacketProperty.NormalPressure)) { pressureData = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.NormalPressure); } else { pressureData = new int[xData.Length]; length = pressureData.Length; for (i = 0; i < length; ++i) { pressureData[i] = (255 - 0) / 2; } } // If the time data is included take it, otherwise set to the timestamp plus and increment ulong[] adjustedTime = new ulong[xData.Length]; int[] timerTick; if (IsPropertyIncluded(inkStroke, Microsoft.Ink.PacketProperty.TimerTick)) { timerTick = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.TimerTick); length = timerTick.Length; for (i = 0; i < length; i++) { // This may be incorrect, we never encountered this because Microsoft Journal doesn't save TimerTick data. // We know that the timestamp of a stroke is made when the pen is lifted. // Add the time of the stroke to each offset adjustedTime[i] = theTime + (ulong)timerTick[i] * 10000; } } else { timerTick = new int[xData.Length]; length = timerTick.Length; for (i = 0; i < length; i++) { // We believe this to be the standard sample rate. The multiplication by 1,000 is to convert from // seconds to milliseconds. // // Our time is in the form of milliseconds since Jan 1, 1970 // // NOTE: The timestamp for the stroke is made WHEN THE PEN IS LIFTED adjustedTime[i] = theTime - (ulong)((1 / SAMPLE_RATE * 1000) * (length - i)); } } // Create the array of ID's as new Guid's Guid[] idData = new Guid[xData.Length]; length = idData.Length; for (i = 0; i < length; i++) { idData[i] = Guid.NewGuid(); } // Create the internal representation Sketch.Stroke converterStroke = new Sketch.Stroke(); converterStroke.XmlAttrs.Id = System.Guid.NewGuid(); converterStroke.XmlAttrs.Name = "stroke"; converterStroke.XmlAttrs.Time = (ulong)theTime; converterStroke.XmlAttrs.Type = "stroke"; converterStroke.XmlAttrs.Source = "Converter"; Sketch.Substroke substroke = new Sketch.Substroke(); substroke.XmlAttrs.Id = System.Guid.NewGuid(); substroke.XmlAttrs.Name = "substroke"; substroke.XmlAttrs.Time = theTime; substroke.XmlAttrs.Type = "substroke"; substroke.XmlAttrs.Color = color; substroke.XmlAttrs.Height = height; substroke.XmlAttrs.Width = width; substroke.XmlAttrs.PenTip = penTip; substroke.XmlAttrs.Raster = raster; substroke.XmlAttrs.X = x; substroke.XmlAttrs.Y = y; //substroke.XmlAttrs.LeftX = leftx; //substroke.XmlAttrs.TopY = topy; substroke.XmlAttrs.Source = "ConverterJnt"; substroke.XmlAttrs.Start = idData[0]; substroke.XmlAttrs.End = idData[idData.Length - 1]; // Add all of the points to the stroke length = inkStroke.PacketCount; for (i = 0; i < length; i++) { Sketch.Point toAdd = new Sketch.Point(); toAdd.XmlAttrs.Name = "point"; toAdd.XmlAttrs.X = Convert.ToSingle(xData[i]); toAdd.XmlAttrs.Y = Convert.ToSingle(yData[i]); toAdd.XmlAttrs.Pressure = Convert.ToUInt16(pressureData[i]); toAdd.XmlAttrs.Time = Convert.ToUInt64(adjustedTime[i]); toAdd.XmlAttrs.Id = idData[i]; substroke.AddPoint(toAdd); } converterStroke.AddSubstroke(substroke); return(converterStroke); }