public override void SerializePoints(Stream stream, int numPoints) { IFormatter formatter = new BinaryFormatter(); // Calculate the number of strokes to serialize int index = this.myInk.Strokes.Count; int countLeft = numPoints; while (countLeft > 0 && index > 0) { index--; countLeft -= this.myInk.Strokes[index].GetPoints().Length; } // Index is now -1 or the first stroke to send. if (index < 0) { index = 0; } if (countLeft < 0) { countLeft += this.myInk.Strokes[index].GetPoints().Length; } // If there is a partial stroke, serialize it specially if (countLeft > 0) { formatter.Serialize(stream, true); // Flag that there is a partial stroke. } else { formatter.Serialize(stream, false); // Flag that there is no partial stroke. } // Serialize just a zero (length) for an empty scribble. if (this.myInk.Strokes.Count - index == 0) { formatter.Serialize(stream, 0); } else { // Serialize all remaining strokes completely Ink.Ink ink = new Ink.Ink(); int[] ids = new int[this.myInk.Strokes.Count - index]; for (int i = index; i < this.myInk.Strokes.Count; i++) { ids[i - index] = this.myInk.Strokes[i].Id; } // Note: AddStrokesAtRectangle is used since the documentation for AddStrokes // states that the strokes must *already* be in the ink object (so, it's only // used for updating custom strokes collections??). Ink.Strokes strokes = this.myInk.CreateStrokes(ids); ink.AddStrokesAtRectangle(strokes, strokes.GetBoundingBox()); byte[] inkBytes = ink.Save(); formatter.Serialize(stream, inkBytes.Length); stream.Write(inkBytes, 0, inkBytes.Length); } }
/// <summary> /// Find Stroke from Guid /// </summary> /// The original version was much too slow for the archive replay scenario. /// <param name="scribble"></param> /// <param name="guid"></param> /// <param name="stroke"></param> /// <param name="guidTag"></param> /// <returns></returns> private bool FastFindStrokeFromGuid(InkScribble scribble, Guid guid, out Ink.Stroke stroke, Guid guidTag) { Ink.Ink ink = scribble.Ink; if (this.myGuidReverseTable.Contains(guid)) { if (((ScribbleIntPair)this.myGuidReverseTable[guid]).scribble == scribble) { ScribbleIntPair pair = (ScribbleIntPair)this.myGuidReverseTable[guid]; /// The count can be zero right after a clear slide or clear deck operation /// if count is zero, CreateStrokes will except. if (pair.scribble.Count == 0) { stroke = null; return(false); } Ink.Strokes targetStrokes = null; try { targetStrokes = ink.CreateStrokes(new int[] { pair.id }); } catch (Exception e) { //not clear when this would happen? stroke = null; Trace.WriteLine("FastFindStrokeFromGuid: Exception during CreateStrokes: " + e.ToString()); return(false); } if (targetStrokes.Count < 1) //not clear when this would happen? { stroke = null; Trace.WriteLine("FastFindStrokeFromGuid: Found target with zero stroke count."); return(false); } // Found it. stroke = targetStrokes[0]; return(true); } else { //This happens when we revisit slides we've been on previously this.myGuidReverseTable.Remove(guid); stroke = null; return(false); } } else { stroke = null; return(false); } }
private void menuStrokeInformation_Click(object sender, EventArgs e) { Sketch.Sketch sketch = sketchPanel.Sketch; FeatureSketch sketchFeatures = new FeatureSketch(ref sketch); Microsoft.Ink.Strokes selected = sketchPanel.InkSketch.Ink.Strokes; Microsoft.Ink.Stroke s = selected[selected.Count - 1]; Sketch.Substroke ss = sketchPanel.InkSketch.GetSketchSubstrokeByInkId(s.Id); StrokeInfoForm.strokeInfoForm sif = new StrokeInfoForm.strokeInfoForm(sketchFeatures.GetFeatureStrokeByStrokeGUID(ss.Id), sketchFeatures, s, ss); sif.Show(); }
/// <summary> /// Converts a Sketch shape into a collection of Microsoft.Ink strokes. /// </summary> /// <param name="shape">The shape to convert</param> /// <returns>The desired ink strokes</returns> public Microsoft.Ink.Strokes convertToInk(Sketch.Shape shape) { // Create a collection of strokes Microsoft.Ink.Ink ink = new Microsoft.Ink.Ink(); Microsoft.Ink.Strokes inkStrokes = ink.CreateStrokes(); Sketch.Substroke[] sketchStrokes = shape.Substrokes; // Add the substrokes of our format to the strokes collection. foreach (Sketch.Substroke sub in sketchStrokes) { inkStrokes.Add(convertToInk(sub, ink)); } return(inkStrokes); }
/// <summary> /// Constructor /// </summary> /// <param name="sketch">Sketch to add a label to</param> /// <param name="substrokes">Substrokes to label</param> /// <param name="label">Label to apply</param> /// <param name="labelColor">Color of the applied label</param> /// <param name="inkStrokes">InkOverlay strokes</param> public ApplyLabel(Sketch.Sketch sketch, ArrayList substrokes, string label, System.Drawing.Color labelColor, Microsoft.Ink.Strokes inkStrokes) { this.sketch = sketch; this.substrokes = substrokes; this.label = label; this.labelColor = labelColor; this.inkStrokes = inkStrokes; // Initialize the original colors of the inkStrokes this.origColors = new System.Drawing.Color[inkStrokes.Count]; int count = 0; foreach (Microsoft.Ink.Stroke stroke in inkStrokes) { origColors[count++] = stroke.DrawingAttributes.Color; } }
/// <summary> /// /// </summary> /// <param name="document"></param> /// <param name="strokes"></param> /// <param name="label"></param> public void createShapeWithLabel(MakeXML document, Microsoft.Ink.Strokes strokes, string label) { //Create the new shape we will add Shape toAdd = new Shape(System.Guid.NewGuid().ToString(), label, "", label); //Extra information for the shape toAdd.Source = "LabelerSession" + this.GetHashCode().ToString(); toAdd.Width = strokes.GetBoundingBox().Width.ToString(); toAdd.Height = strokes.GetBoundingBox().Height.ToString(); toAdd.X = strokes.GetBoundingBox().X.ToString(); toAdd.Y = strokes.GetBoundingBox().Y.ToString(); ulong currentTime; ulong bestTime = 0; foreach (Microsoft.Ink.Stroke stroke in strokes) { int id = stroke.Id; Stroke s = (Stroke)idToCStroke[id]; Stroke.Arg arg = new Stroke.Arg(s.Type, s.Id); toAdd.Args.Add(arg); currentTime = Convert.ToUInt64(s.Time); if (currentTime > bestTime) { bestTime = currentTime; } } toAdd.Time = bestTime.ToString(); document.addShape(toAdd); }
private bool FindStrokeFromGuid(InkScribble scribble, Guid guid, out Ink.Stroke stroke, Guid guidTag) { Ink.Ink ink = scribble.Ink; // Check if the guid tables are out of date. This might be indicated by either: // * The guid is not in the reverse table. // * The reverse table entry's scribble does not match the given scribble. // If the tables are out of date, update the entries for this scribble object. if (!this.myGuidReverseTable.Contains(guid) || ((ScribbleIntPair)this.myGuidReverseTable[guid]).scribble != scribble) { // Ensure that, at the least, the stale entry is removed. this.myGuidReverseTable.Remove(guid); // Refresh entries for all strokes in this scribble. foreach (Ink.Stroke s in ink.Strokes) { try { if (s.ExtendedProperties.DoesPropertyExist(guidTag)) { Guid strokeGuid = new Guid((string)s.ExtendedProperties[guidTag].Data); this.myGuidReverseTable[strokeGuid] = new ScribbleIntPair(scribble, s.Id); this.myGuidTable[new ScribbleIntPair(scribble, s.Id)] = strokeGuid; } } catch { //this try/catch because I once saw an exception thrown here. Not sure if it was a bug // in the data, the TPC SDK, or in my code.. Anyway it seemed safe to ignore. } } } // If the guid is still not in the table, it is not found. if (!this.myGuidReverseTable.Contains(guid)) { stroke = null; return(false); } // Can we find the specific id sought? ScribbleIntPair pair = (ScribbleIntPair)this.myGuidReverseTable[guid]; //This try/catch is a hack to deal with multiple-play (archive) scenario. //I believe the real fix is to catch WMP stop and postion change events and //to rebuild guid tables and InkScribble appropriately for the new media position. Ink.Strokes targetStrokes = null; try { targetStrokes = ink.CreateStrokes(new int[] { pair.id }); } catch { stroke = null; return(false); } if (targetStrokes.Count < 1) { stroke = null; return(false); } // Found it. stroke = targetStrokes[0]; return(true); }
/// <summary> /// Method stub /// </summary> override public void UnThickenLabel(Microsoft.Ink.Strokes previousSelection) { // Method stub }
/// <summary> /// Method stub /// </summary> override public void ThickenLabel(Microsoft.Ink.Strokes newSelection) { // Method stub }
private void sketchInk_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { // Handles hiding our label menu if we clicked outside its bounds if (this.lTool.LabelMenu.Visible) { System.Drawing.Rectangle labelBoundingBox = new Rectangle(this.lTool.LabelMenu.Location, this.lTool.LabelMenu.Size); if (labelBoundingBox.Contains(new System.Drawing.Point(e.X, e.Y))) { this.lassoPoints.Clear(); this.mouseDown = false; return; } else { this.lTool.LabelMenu.Hide(); } } // Don't do anything if we were moving or resizing the selection if (this.selectionMoving || this.selectionResizing) { this.lassoPoints.Clear(); this.mouseDown = false; return; } // Clear our current Selection // I don't know why this is required, but if we don't our strokesSelected becomes // bloated for some odd reason... //this.inkPic.Selection.Clear(); // The maximum number of points allowed in the lasso for the MouseUp // to be considered a click const int LASSOTHRESHOLD = 10; if (this.lassoPoints.Count < LASSOTHRESHOLD) { this.clicked = true; } else { this.clicked = false; } // Clear our lassoPoints holder this.lassoPoints.Clear(); this.mouseDown = false; // Radius (in ink space coordiantes) float farRadius = (float)(2 * closeRadius); // Cursor point (in ink space coordinates) System.Drawing.Point cursorPt = new System.Drawing.Point(e.X, e.Y); this.inkPic.Renderer.PixelToInkSpace(this.inkPic.CreateGraphics(), ref cursorPt); // Get the strokes close to the point Microsoft.Ink.Strokes justClicked = this.inkPic.Ink.HitTest(cursorPt, closeRadius); foreach (Microsoft.Ink.Stroke s in justClicked) { Console.WriteLine(s.Id); } // Initialize the strokesClicked holder if (this.strokesClicked == null) { this.strokesClicked = justClicked; this.inkPic.Selection = this.strokesClicked; } // Checks to see if we haven't clicked on anything else if (justClicked.Count == 0 && this.clicked) { justClicked = this.inkPic.Ink.HitTest(cursorPt, farRadius); // Clear the strokesClicked holder if we clicked far enough away // from strokes if (justClicked.Count == 0) { this.strokesClicked.Clear(); } this.inkPic.Selection = this.strokesClicked; } // Add or remove what we just clicked on else if (this.clicked) { foreach (Microsoft.Ink.Stroke s in justClicked) { if (this.strokesClicked.Contains(s)) { this.strokesClicked.Remove(s); } else { this.strokesClicked.Add(s); } } this.inkPic.Selection = this.strokesClicked; } // Trick to ensure we update the selection anyway else { this.inkPic.Selection = this.inkPic.Selection; } }
public OpenFragWindow(Microsoft.Ink.Strokes selection, Hashtable mIdToSubstroke) { this.selection = selection; this.mIdToSubstroke = mIdToSubstroke; }
/// <summary> /// Gets label data for a given group of Microsoft strokes /// </summary> public void UpdateLabelMenu(Microsoft.Ink.Strokes selection) { if (this.domainInfo != null && selection.Count > 0) { for (int i = 0; i < this.labelList.Items.Count; i++) { string currLabel = this.domainInfo.GetLabel(i); bool labelPresentInAll = true; Sketch.Shape foundShape = null; foreach (Microsoft.Ink.Stroke stroke in selection) { int temp = stroke.Id; Sketch.Substroke currSelection = (this.labelerPanel.getSubstrokeByMId(temp) as Sketch.Substroke); List <Sketch.Shape> labelShapes = currSelection.ParentShapes; bool labelPresent = false; foreach (Sketch.Shape labelShape in labelShapes) { if (labelShape.XmlAttrs.Type as String == currLabel) { if (foundShape == null) { foundShape = labelShape; labelPresent = true; break; } else if (foundShape == labelShape) { labelPresent = true; break; } } } if (!labelPresent) { labelPresentInAll = false; break; } } // Check or not? if (labelPresentInAll) { this.labelList.SetItemChecked(i, true); } else { this.labelList.SetItemChecked(i, false); } } // Set our previously selected label value to the corresponding value if (this.previousLabelSelected != OUT_OF_BOUNDS) { this.previousLabel.SetItemChecked(0, this.labelList.GetItemChecked(this.previousLabelSelected)); } } }