Пример #1
0
        /// <summary>
        /// Adding one stroke
        /// </summary>
        /// <param name="ink"></param>
        /// <param name="guid"></param>
        /// <param name="finished"></param>
        public void AddInk(Microsoft.Ink.Ink newInk, Guid guid)
        {
            if (newInk.Strokes.Count > 1)
            {
                AddInk(newInk);
            }
            else if (newInk.Strokes.Count > 0)
            {
                if (guid.Equals(Guid.Empty))
                {
                    throw new ApplicationException("Ink Guid must not be Guid.Empty.");
                }

                if (newInk.Strokes[0].DrawingAttributes.Transparency != 255)
                {
                    //Ignore invisible strokes.  These can occur in CP when the user erases individual strokes.

                    if (newInk.Strokes[0].DrawingAttributes.Transparency == 0)
                    {
                        AddInkToInk(ref opaqueInk, newInk, guid);
                    }
                    else
                    {
                        AddInkToInk(ref transparentInk, newInk, guid);
                    }

                    dirtyBit = true;
                }
            }
        }
Пример #2
0
            public void InkExport(Microsoft.Ink.PersistenceFormat persistenceFormat, string filterString)
            {
                byte[] buffer = null;

                //variables used to create filename
                string file = null;
                string ext  = null;

                string defaultFileName = "SavedInk";

                int slideIndex = 0;
                //Create a new save file dialog
                SaveFileDialog saveFileDialog = new SaveFileDialog();

                saveFileDialog.Filter   = filterString;
                saveFileDialog.FileName = defaultFileName;
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    //Iterate throught the slide deck to check for ink on each one
                    using (this.m_Model.Workspace.Lock()) {
                        using (Synchronizer.Lock(this.m_Model.Workspace.CurrentDeckTraversal.Value.SyncRoot)) {
                            DeckModel deck = this.m_Model.Workspace.CurrentDeckTraversal.Value.Deck;
                            using (Synchronizer.Lock(deck.SyncRoot)) {
                                foreach (SlideModel slide in deck.Slides)
                                {
                                    using (Synchronizer.Lock(slide.SyncRoot)) {
                                        foreach (SheetModel sheet in slide.AnnotationSheets)
                                        {
                                            if (sheet is InkSheetModel)
                                            {
                                                using (Synchronizer.Lock(sheet.SyncRoot)) {
                                                    Microsoft.Ink.Ink ink = ((InkSheetModel)sheet).Ink;
                                                    if (ink.Strokes.Count != 0)
                                                    {
                                                        //figure out the filename
                                                        string fileNameTemp = saveFileDialog.FileName;
                                                        ext  = Path.GetExtension(fileNameTemp);
                                                        file = Path.GetFileNameWithoutExtension(fileNameTemp);
                                                        string n        = slideIndex.ToString();
                                                        string fileName = file + "[" + n + "]" + ext;
                                                        buffer = ink.Save(persistenceFormat);

                                                        //open a stream and output the buffer
                                                        FileStream myStream = System.IO.File.Create(fileName);
                                                        myStream.Write(buffer, 0, buffer.Length);
                                                        myStream.Close();

                                                        slideIndex++;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
Пример #3
0
        /// <summary>
        /// Constructor for the WorkPath class
        /// </summary>
        /// <param name="projectPath">String containing full filename of Xilinx .ise
        /// project file</param>
        /// <param name="filePath">String containing full filename of sketch xml</param>
        /// <param name="ink">Microsoft.Ink.Ink object</param>
        public WorkPath(String projectPath, String filePath, Microsoft.Ink.Ink ink)
        {
            this.filePath = filePath;

            //converts ink to sketch
            ReadInk newSketch = new ReadInk(ink);

            this.sketch      = newSketch.Sketch;
            this.projectPath = projectPath;
        }
Пример #4
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="param">The event parameters</param>
 public InkDrawingEvent( ArrayList param )
 {
     PlaybackInk = new Microsoft.Ink.Ink();
     if( param.Count >= 1 ) {
         LoadRecordedData( (string)param[0] );
     }
     if( param.Count >= 2 ) {
         this.m_Path = Script.ParsePath( (string)param[1] );
     }
 }
Пример #5
0
        /// <summary>
        /// Overlay one stroke on the image.
        /// </summary>
        /// <param name="img"></param>
        /// <param name="s"></param>
        /// <param name="size"></param>
        /// PRI2: I believe we can use the DibGraphicsBuffer (see opaque ink handling above) to improve the
        /// look of the transparency.  This currently has the following shortcoming:  The colors produced by the exported gif
        /// from CP's highlight pens have some whiteness which causes a little fog over the dark colors
        /// below, for example the yellow highlight over a black background results in a lighter dark color,
        /// no longer quite black.  In contrast the native ink mixing gives us nearly the original black.  It is as if
        /// the colors are on colored but clear mylar that overlay one another.  It's probably possible to get this effect
        /// with DrawImage somehow??
        private void addTransparentStroke(Image img, Microsoft.Ink.Strokes s, double size)
        {
            Microsoft.Ink.Ink tmpInk = new Microsoft.Ink.Ink();
            tmpInk.AddStrokesAtRectangle(s, s.GetBoundingBox());
            //Make a GIF Image from the Stroke.  Note that this image is assumed to be in a 500x500 pixel space.
            byte[] ba     = tmpInk.Save(Microsoft.Ink.PersistenceFormat.Gif);
            Image  inkImg = Image.FromStream(new MemoryStream(ba));

            Graphics g = Graphics.FromImage(img);

            //Get the origin from the ink Bounding Box (in ink space)
            Rectangle inkBB = tmpInk.GetBoundingBox();

            //Convert the origin of the ink rectangle to pixel space (500x500)
            Microsoft.Ink.Renderer r = new Microsoft.Ink.Renderer();
            Point inkOrigin          = inkBB.Location;

            r.InkSpaceToPixel(g, ref inkOrigin);

            //Convert the transparency coefficient from 0-255 with 0==opaque to the range of 0-1 with 1==opaque.
            int   t1 = Math.Abs(tmpInk.Strokes[0].DrawingAttributes.Transparency - 255);
            float t2 = (float)t1 / 255f;

            //Setting transparency with a ColorMatrix
            float[][] ptsArray =
            {
                new float[] { 1, 0, 0,  0, 0 }, //r
                new float[] { 0, 1, 0,  0, 0 }, //g
                new float[] { 0, 0, 1,  0, 0 }, //b
                new float[] { 0, 0, 0, t2, 0 }, //alpha
                new float[] { 0, 0, 0,  0, 1 }
            };
            ColorMatrix     clrMatrix     = new ColorMatrix(ptsArray);
            ImageAttributes imgAttributes = new ImageAttributes();

            imgAttributes.SetColorMatrix(clrMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

            //Adjust Y origin to account for horizontal scroll.  (scrollPos becomes more positive as ink goes upward.)
            float scrolledYInkOrigin = (float)inkOrigin.Y - (500 * (float)scrollPos); //Still in 500x500 space

            //Scale and locate the destination rectangle of the ink within the slide image:
            RectangleF destRect = new RectangleF(
                (float)inkOrigin.X * ((float)img.Width / 500f) * (float)size,
                scrolledYInkOrigin * ((float)img.Height / 500f) * (float)size,
                (float)inkImg.Width * ((float)img.Width / 500f) * (float)size,
                (float)inkImg.Height * ((float)img.Height / 500f) * (float)size);

            Rectangle destRect2 = new Rectangle((int)destRect.X, (int)destRect.Y, (int)destRect.Width, (int)destRect.Height);

            //Draw the overlay:
            g.DrawImage(inkImg, destRect2, 0, 0, inkImg.Width, inkImg.Height, GraphicsUnit.Pixel, imgAttributes);
            g.Dispose();
        }
Пример #6
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="param">The event parameters</param>
 public InkDrawingEvent(ArrayList param)
 {
     PlaybackInk = new Microsoft.Ink.Ink();
     if (param.Count >= 1)
     {
         LoadRecordedData((string)param[0]);
     }
     if (param.Count >= 2)
     {
         this.m_Path = Script.ParsePath((string)param[1]);
     }
 }
Пример #7
0
        public SlideImage()
        {
            whiteboardBackground = true;
            slideBitmap          = null;
            rawCompositeImage    = null;
            dirtyBit             = true;
            opaqueInk            = null;
            transparentInk       = null;
            filePath             = null;
            quickPoll            = null;

            lastSize    = 1.0;
            lastBgColor = Color.PapayaWhip;

            scrollPos    = 0.0;
            scrollExtent = 1.5;
        }
Пример #8
0
        /// <summary>
        /// Adding multiple strokes (which can't be erased individually because there are no Guids)
        /// Specifically, this is for student submission overlays.
        /// There are also some CP3 scenarios such as when the instructor opens a CP3 file that has pre-existing ink.
        /// </summary>
        /// <param name="ink"></param>
        public void AddInk(Microsoft.Ink.Ink newInk)
        {
            if ((newInk != null) && (newInk.Strokes.Count > 0))
            {
                //separate transparent and opaque strokes
                List <int> transparentStrokes = new List <int>();
                List <int> opaqueStrokes      = new List <int>();

                //iterate over strokes, adding the ink ids to the correct list
                foreach (Microsoft.Ink.Stroke s in newInk.Strokes)
                {
                    if ((s.DrawingAttributes.Transparency != 0) && (s.DrawingAttributes.Transparency != 255))
                    {
                        transparentStrokes.Add(s.Id);
                    }
                    else
                    {
                        opaqueStrokes.Add(s.Id);
                    }
                }

                //Add transparent strokes to transparentInk.
                if (transparentStrokes.Count > 0)
                {
                    Microsoft.Ink.Strokes tStrokes = newInk.CreateStrokes((int[])transparentStrokes.ToArray());
                    if (transparentInk == null)
                    {
                        transparentInk = new Microsoft.Ink.Ink();
                    }
                    transparentInk.AddStrokesAtRectangle(tStrokes, tStrokes.GetBoundingBox());
                    dirtyBit = true;
                }

                //Add opaque strokes to opaqueInk.
                if (opaqueStrokes.Count > 0)
                {
                    Microsoft.Ink.Strokes oStrokes = newInk.CreateStrokes((int[])opaqueStrokes.ToArray());
                    if (opaqueInk == null)
                    {
                        opaqueInk = new Microsoft.Ink.Ink();
                    }
                    opaqueInk.AddStrokesAtRectangle(oStrokes, oStrokes.GetBoundingBox());
                    dirtyBit = true;
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Loads an Ink instance and synchronizes Sketch
        /// </summary>
        /// <param name="ink">The Ink to load</param>
        public void LoadInk(Microsoft.Ink.Ink ink)
        {
            unsubscribeToInk();

            this.Clear();

            mInk = ink;

            // Load strokes
            using (Microsoft.Ink.Strokes iStrokes = ink.Strokes)
            {
                foreach (Microsoft.Ink.Stroke iStroke in iStrokes)
                {
                    AddInkStroke(iStroke);
                }
            }

            subscribeToInk();
        }
Пример #10
0
        private void removeFromInk(Microsoft.Ink.Ink ink, Guid guid)
        {
            if (ink == null)
            {
                return;
            }

            foreach (Microsoft.Ink.Stroke s in ink.Strokes)
            {
                if (s.ExtendedProperties.DoesPropertyExist(Constants.CPInkExtendedPropertyTag))
                {
                    if (s.ExtendedProperties[Constants.CPInkExtendedPropertyTag].Data.Equals(guid.ToString()))
                    {
                        ink.DeleteStroke(s);
                        dirtyBit = true;
                        return;
                    }
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Constructor helper.  If both arguments are null, an empty
        /// instance of this class is created.  If Ink or Sketch
        /// is null, then one object is synchronized to the other
        /// (e.g. if ink is null, an empty Ink will be created and
        /// synchronized with Sketch).  If neither argument is null, then
        /// Sketch will be synchronized with Ink.  Subscribes to Ink events
        /// after any synchronization.
        /// </summary>
        /// <param name="ink">The Ink with which to (possibly) synchronize</param>
        /// <param name="sketch">The Sketch with which to (possibly) synchronize</param>
        protected virtual void init(Microsoft.Ink.Ink ink, FeatureSketch featureSketch)
        {
            // Instantiate new Ink and/or Sketch where necessary
            if (ink == null)
            {
                mInk = new Microsoft.Ink.Ink();
            }
            else
            {
                mInk = ink;
            }

            if (featureSketch == null)
            {
                mFeatureSketch        = new FeatureSketch();
                Sketch.XmlAttrs.Id    = System.Guid.NewGuid();
                Sketch.XmlAttrs.Units = DefaultSketchUnits;
            }
            else
            {
                mFeatureSketch = featureSketch;
            }

            // Intialize other fields
            mReadJnt       = new ReadJnt();
            ink2sketchStr  = new Dictionary <int, Guid?>();
            sketchStr2ink  = new Dictionary <Guid?, int>();
            substrokeIdMap = new Dictionary <Guid?, Substroke>();

            // Synchronize Ink or Sketch as necessary
            if (ink == null && featureSketch != null)
            {
                LoadFeatureSketch(featureSketch);
            }
            else // (ink != null && featureSketch == null)
            {
                LoadInk(ink);
            }

            subscribeToInk();
        }
Пример #12
0
        /// <summary>
        /// Clears the contents of this InkSketch.  Deletes
        /// all Ink and Sketch strokes and maintains
        /// synchronization between Ink and Sketch.
        /// </summary>
        public virtual void Clear()
        {
            mFeatureSketch        = new FeatureSketch();
            Sketch.XmlAttrs.Id    = System.Guid.NewGuid();
            Sketch.XmlAttrs.Units = DefaultSketchUnits;

            mInk = new Microsoft.Ink.Ink();

            if (ink2sketchStr != null)
            {
                ink2sketchStr.Clear();
            }
            if (sketchStr2ink != null)
            {
                sketchStr2ink.Clear();
            }
            if (substrokeIdMap != null)
            {
                substrokeIdMap.Clear();
            }
        }
Пример #13
0
        /// <summary>
        /// Add a stroke to an Ink
        /// </summary>
        /// <param name="destInk"></param>
        /// <param name="srcInk"></param>
        /// <param name="guid"></param>
        private void AddInkToInk(ref Microsoft.Ink.Ink destInk, Microsoft.Ink.Ink srcInk, Guid guid)
        {
            if (destInk == null)
            {
                //first stroke: create new ink
                destInk = new Microsoft.Ink.Ink();
            }

            //Remove the stroke, if it exists.
            RemoveInk(guid);

            //Set the extended property.
            if (srcInk.Strokes[0].ExtendedProperties.DoesPropertyExist(Constants.CPInkExtendedPropertyTag))
            {
                srcInk.Strokes[0].ExtendedProperties.Remove(Constants.CPInkExtendedPropertyTag);
            }
            srcInk.Strokes[0].ExtendedProperties.Add(Constants.CPInkExtendedPropertyTag, guid.ToString());

            //Add stroke
            destInk.AddStrokesAtRectangle(srcInk.Strokes, srcInk.Strokes.GetBoundingBox());
        }
Пример #14
0
        /// <summary>
        ///  Loads Ink Data from a specified ISF or JNT file
        /// </summary>
        /// <param name="inkDataFileName">
        /// The file to load the Ink Data from.</param>
        protected void LoadRecordedData(string inkDataFileName)
        {
            // First, reset the Ink object
            PlaybackInk.DeleteStrokes();

            if (!File.Exists(inkDataFileName))
            {
                MessageBox.Show("Cannot find file: " + inkDataFileName);
                return;
            }

            // Read in the specified file
            FileStream isfStream = new FileStream(inkDataFileName, FileMode.Open, FileAccess.Read);

            // Verify the filestream creation was successful
            if (null != isfStream && isfStream.Length > 0)
            {
                byte[] isfBytes = new byte[isfStream.Length];

                // read in the ISF doc
                isfStream.Read(isfBytes, 0, (int)isfStream.Length);

                // Load the ink into a new Temporary object
                // Once an Ink object has been "dirtied" it cannot load ink
                Microsoft.Ink.Ink TemporaryInk = new Microsoft.Ink.Ink();

                // Load the ISF into the ink object
                TemporaryInk.Load(isfBytes);

                // Add the loaded strokes to our Ink object
                PlaybackInk.AddStrokesAtRectangle(TemporaryInk.Strokes, TemporaryInk.Strokes.GetBoundingBox());

                // Close the file stream
                isfStream.Close();
            }
        }
Пример #15
0
        /// <summary>
        /// Handle frames from a native RTDocument generator such as the CXP presentation tool
        /// </summary>
        /// <param name="rtobj"></param>
        private void acceptRTDocFrame(object rtobj)
        {
            ///Notes about RTDocuments:
            ///
            /// RTDocuments have Resources and Organizations.  Resources contain Pages/Images etc while Organizations
            /// contain the TOC/titles, etc. The TOC Nodes contain references to the resources and resource IDs.
            /// The navigation message RTNodeChanged just tells us the organization node ID, while
            /// Page and ink messages only contain the Resource ID.  RTDocument messages contain the TOC which maps pages and org nodes.
            /// PageAdds will not have an existing TocNode in the RTDocument map, but they carry their own TocNode property.
            ///
            /// For this application, we only care about having one unique page identifier.  We take the strategy of storing
            /// SlideImages under the resource Identifier, and maintaining a lookup table of Organization identifier to
            /// resource identifier.  We use this table to resolve Organization identifiers when navigation messages are received.

            if (rtobj is RTDocument)
            {
                RTDocument rtd = (RTDocument)rtobj;
                //Keep the mapping of TocNode.Identifier to TocNode.ResourceIdentifier
                foreach (TOCNode tn in rtd.Organization.TableOfContents)
                {
                    if (!orgToResource.ContainsKey(tn.Identifier))
                    {
                        orgToResource.Add(tn.Identifier, tn.ResourceIdentifier);
                    }
                    else
                    {
                        orgToResource[tn.Identifier] = tn.ResourceIdentifier;
                    }
                }

                //There is an implicit navigation to the first slide here.
                this.currentSlide.SetRTDocReference(rtd.Organization.TableOfContents[0].ResourceIdentifier);
            }
            else if (rtobj is Page)
            {
                //These are slide deck pages
                //p.Identifier is a Resource Identifier.  Store the image under that Identifier.
                Page p = (Page)rtobj;
                if (!slideImages.ContainsKey(p.Identifier.ToString()))
                {
                    slideImages.Add(p.Identifier.ToString(), new SlideImage());
                }
                ((SlideImage)slideImages[p.Identifier.ToString()]).SetImage(p.Image, false);
            }
            else if (rtobj is RTPageAdd)
            {
                //These are dynamically added pages such as WB and screenshots
                RTPageAdd rtpa = (RTPageAdd)rtobj;
                //RTPageAdd comes with a TocNode.  Store the mapping of resource ID to TocNode.Identifier
                if (!orgToResource.ContainsKey(rtpa.TOCNode.Identifier))
                {
                    orgToResource.Add(rtpa.TOCNode.Identifier, rtpa.Page.Identifier);
                }
                else
                {
                    orgToResource[rtpa.TOCNode.Identifier] = rtpa.Page.Identifier;
                }

                //Store the page Image under the resource ID.
                if (!slideImages.ContainsKey(rtpa.Page.Identifier.ToString()))
                {
                    slideImages.Add(rtpa.Page.Identifier.ToString(), new SlideImage());
                }
                ((SlideImage)slideImages[rtpa.Page.Identifier.ToString()]).SetImage(rtpa.Page.Image, false);
            }
            else if (rtobj is RTNodeChanged)
            {
                RTNodeChanged rtnc = (RTNodeChanged)rtobj;
                //Look up the resource ID and update curent page.
                if (orgToResource.ContainsKey(rtnc.OrganizationNodeIdentifier))
                {
                    currentSlide.SetRTDocReference(((Guid)orgToResource[rtnc.OrganizationNodeIdentifier]));
                }
                else
                {
                    //Indicate slide missing by setting currentSlide reference to Guid.Empty
                    currentSlide.SetRTDocReference(Guid.Empty);
                }
            }
            else if (rtobj is RTStroke)
            {
                RTStroke rts = (RTStroke)rtobj;
                //apply the ink to the given Page Identifier.  Create a new SlideImage if necessary.
                if (!slideImages.ContainsKey(rts.PageIdentifier.ToString()))
                {
                    slideImages.Add(rts.PageIdentifier.ToString(), new SlideImage());
                }
                Microsoft.Ink.Ink ink = rts.Stroke.Ink.Clone();
                for (int i = 0; i < ink.Strokes.Count; i++)
                {
                    ink.Strokes[i].Scale(500f / 960f, 500f / 720f);
                }

                ((SlideImage)slideImages[rts.PageIdentifier.ToString()]).AddInk(ink, rts.StrokeIdentifier);

                //There appears to be an implicit navigation here.
                currentSlide.SetRTDocReference(rts.PageIdentifier);
            }
            else if (rtobj is RTStrokeRemove)
            {
                RTStrokeRemove rtsr = (RTStrokeRemove)rtobj;
                //Use the PageIdentifer to identify the page from which to remove the stroke.
                if (slideImages.ContainsKey(rtsr.PageIdentifier.ToString()))
                {
                    ((SlideImage)slideImages[rtsr.PageIdentifier.ToString()]).RemoveInk(rtsr.StrokeIdentifier);
                }
            }
            else if (rtobj is RTFrame)
            {
                RTFrame rtf = (RTFrame)rtobj;
                if (rtf.ObjectTypeIdentifier == Constants.RTDocEraseAllGuid)
                {
                    //Erase all ink on the current slide.
                    if ((currentSlide.IsSet) && (slideImages.ContainsKey(currentSlide.GetStringHashCode())))
                    {
                        ((SlideImage)slideImages[currentSlide.GetStringHashCode()]).RemoveAllInk();
                    }
                }
                else
                {
                    Debug.WriteLine("Unhandled RTFrame type.");
                }
            }
            else
            {
                Debug.WriteLine("Unhandled RT obj:" + rtobj.ToString());
            }
        }
Пример #16
0
        /// <summary>
        ///  Loads Ink Data from a specified ISF or JNT file
        /// </summary>
        /// <param name="inkDataFileName">
        /// The file to load the Ink Data from.</param>
        protected void LoadRecordedData(string inkDataFileName)
        {
            // First, reset the Ink object
            PlaybackInk.DeleteStrokes();

            if( !File.Exists( inkDataFileName ) ) {
                MessageBox.Show( "Cannot find file: " + inkDataFileName );
                return;
            }

            // Read in the specified file
            FileStream isfStream = new FileStream( inkDataFileName, FileMode.Open, FileAccess.Read );

            // Verify the filestream creation was successful
            if (null != isfStream && isfStream.Length > 0) {
                byte[] isfBytes = new byte[isfStream.Length];

                // read in the ISF doc
                isfStream.Read(isfBytes, 0, (int)isfStream.Length);

                // Load the ink into a new Temporary object
                // Once an Ink object has been "dirtied" it cannot load ink
                Microsoft.Ink.Ink TemporaryInk = new Microsoft.Ink.Ink();

                // Load the ISF into the ink object
                TemporaryInk.Load(isfBytes);

                // Add the loaded strokes to our Ink object
                PlaybackInk.AddStrokesAtRectangle(TemporaryInk.Strokes, TemporaryInk.Strokes.GetBoundingBox());

                // Close the file stream
                isfStream.Close();
            }
        }
Пример #17
0
 /// <summary>
 /// Constructor.  Creates an empty Sketch and synchronizes it
 /// with the contents of the given Ink.
 /// </summary>
 /// <param name="ink">The Ink with which to synchronize</param>
 public InkSketch(Microsoft.Ink.Ink ink)
 {
     init(ink, null);
 }