/// <summary> /// Helper class that is run on a different thread that converts the ink coordinates into pixel coordinates /// </summary> /// <param name="extracted">The strokes to convert and add to the model</param> private void HandleInkAddedHelper(Ink extracted) { // Adjust for differences in DPI if (ViewerStateModel.NonStandardDpi) { extracted.Strokes.Transform(ViewerStateModel.DpiNormalizationSendMatrix, true); } // Get the model object to add it to lock (WebService.Instance.GlobalModel) { SimpleWebDeck deck = (SimpleWebDeck)WebService.Instance.GlobalModel.Decks[WebService.Instance.GlobalModel.CurrentDeck]; SimpleWebSlide slide = (SimpleWebSlide)deck.Slides[WebService.Instance.GlobalModel.CurrentSlide - 1]; slide.Inks = new ArrayList(); // Extract each stroke foreach (Stroke s in extracted.Strokes) { // Get the points System.Drawing.Point[] pts = s.GetPoints(); // Convert and remove duplicates bool bFirst = true; ArrayList pts_new = new ArrayList(); System.Drawing.Point last = System.Drawing.Point.Empty; foreach (System.Drawing.Point p in pts) { System.Drawing.Point pNew = new System.Drawing.Point((int)Math.Round(p.X / 26.37f), (int)Math.Round(p.Y / 26.37f)); if (!bFirst && last == pNew) { continue; } bFirst = false; last = pNew; pts_new.Add(pNew); } // Add the points to the model SimpleWebInk stroke = new SimpleWebInk(); stroke.Pts = (System.Drawing.Point[])pts_new.ToArray(typeof(System.Drawing.Point)); stroke.R = s.DrawingAttributes.Color.R; stroke.G = s.DrawingAttributes.Color.G; stroke.B = s.DrawingAttributes.Color.B; stroke.Opacity = (s.DrawingAttributes.RasterOperation == RasterOperation.MaskPen) ? (byte)127 : (byte)255; stroke.Width = s.DrawingAttributes.Width / 26.37f; slide.Inks.Add(stroke); } } WebService.Instance.UpdateModel(); }
/// <summary> /// Handle data posted to up by th web client. /// </summary> /// <param name="parameters">The query string parameters.</param> /// <param name="postData">The post data string.</param> /// <returns>The response text.</returns> private string PostHandler(NameValueCollection parameters, string postData) { // Get the parts of the post data. string[] items = postData.Split(new char[] { '|' }); if (items[0] == STUDENT_SUBMISSION_REQUEST) // Handle student submission. // Deserialize the Array of SimpleStrokeModel from the post data. { int clientId = Convert.ToInt32(items[1]); int deck = Convert.ToInt32(items[2]); int slide = Convert.ToInt32(items[3]); object strokes = JSON.Decode(items[4]); if (strokes is List <object> ) { ArrayList deserializedStrokes = new ArrayList(); List <object> strokesArray = (List <object>)strokes; foreach (object stroke in strokesArray) { if (stroke is List <KeyValuePair <string, object> > ) { SimpleWebInk deserializedStroke = new SimpleWebInk(); List <KeyValuePair <string, object> > strokeObject = (List <KeyValuePair <string, object> >)stroke; foreach (KeyValuePair <string, object> field in strokeObject) { switch (field.Key) { case "c": // Color if (field.Value is List <KeyValuePair <string, object> > ) { List <KeyValuePair <string, object> > color = (List <KeyValuePair <string, object> >)field.Value; foreach (KeyValuePair <string, object> channel in color) { if (channel.Key == "r") { deserializedStroke.R = (byte)Math.Round((double)channel.Value); } else if (channel.Key == "g") { deserializedStroke.G = (byte)Math.Round((double)channel.Value); } else if (channel.Key == "b") { deserializedStroke.B = (byte)Math.Round((double)channel.Value); } } } break; case "w": // Width if (field.Value is double) { deserializedStroke.Width = (float)((double)field.Value); } break; case "o": // Opacity if (field.Value is double) { deserializedStroke.Opacity = (byte)Math.Round((double)field.Value); } break; case "k": // Points if (field.Value is List <object> ) { List <object> points = (List <object>)field.Value; int numPoints = points.Count / 2; System.Drawing.Point[] pts = new System.Drawing.Point[numPoints]; for (int i = 0; i < numPoints; i++) { pts[i].X = (int)((double)points[(i * 2)] * 26.37f); pts[i].Y = (int)((double)points[(i * 2) + 1] * 26.37f); } deserializedStroke.Pts = pts; } break; } } deserializedStrokes.Add(deserializedStroke); } } // Notify listeners that a student submission was received. WebService.Instance.SubmissionReceived(WebServer.Instance, deck, slide, deserializedStrokes); } // Log that we responded to a pong. this.LogSubmissionReceived(clientId, deck, slide); } else if (items[0] == QUICK_POLL_REQUEST) // Handle quick poll. // Notify listeners that a quick poll update was received. { WebService.Instance.QuickPollReceived(WebServer.Instance, new Guid(items[1]), items[2]); } else if (items[0] == PING_REQUEST) // Handle ping request. { String clientId = items[1]; String clientTimestamp = items[2]; String serverTimestamp = WebService.ToUnixTime(System.DateTime.Now).ToString(); // We should respond with the current timestamp. String pong = "{\"u\":" + clientId + ",\"c\":" + clientTimestamp + ",\"s\":" + serverTimestamp + "}"; // Log that we responded to a pong. this.LogPong(Convert.ToInt32(clientId), pong); return(pong); } else if (items[0] == LOG_DUMP_REQUEST) // Handle a client log dump. { String clientId = items[1]; String logDump = items[2]; // Print the dumped log to a file. StreamWriter logFile = new StreamWriter( System.IO.Path.Combine(System.IO.Path.GetTempPath(), "CP_ClientPerformanceLog_" + clientId.ToString() + ".txt")); logFile.Write(logDump); logFile.Close(); } // By default, return an empty json object. return("{}"); }