예제 #1
0
        /// <summary>
        /// Returns the Ink stroke corresponding to the given
        /// Sketch substroke Id.  Returns null if no corresponding
        /// Ink stroke exists.
        /// </summary>
        /// <param name="substr">The Id of the Substroke to look up</param>
        /// <returns>The corresponding Ink stroke</returns>
        public Microsoft.Ink.Stroke GetInkStrokeBySubstrokeId(Guid?substrId)
        {
            if (!sketchStr2ink.ContainsKey(substrId))
            {
                return(null);
            }

            Microsoft.Ink.Stroke iStroke;
            using (Microsoft.Ink.Strokes strokes = mInk.Strokes)
            {
                int index = sketchStr2ink[substrId];

                try
                {
                    iStroke = strokes[index - 1];
                }
                catch (ArgumentException)
                {
                    return(null);
                    // We should never in practice get here,
                    // but if we do, it means an Ink stroke
                    // we reference is missing from mInk
                }
            }

            return(iStroke);
        }
예제 #2
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();
        }
예제 #3
0
        private void addTransparentInkOverlay(Image img, double size)
        {
            //Ink transparency is in the range 0-255 with 0==opaque and 255==invisible.
            //In practice CP sets transparency to 160, but we should be prepared for
            //arbitrary values.
            //We have no assurance that individual strokes won't have different transparencies, so we'll
            //do each stroke as a separate overlay.

            if ((transparentInk != null) && (transparentInk.Strokes.Count > 0))
            {
                foreach (Microsoft.Ink.Stroke s in transparentInk.Strokes)
                {
                    Microsoft.Ink.Strokes strokes = transparentInk.CreateStrokes(new int[] { s.Id });
                    addTransparentStroke(img, strokes, size);
                }
            }
        }
예제 #4
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;
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="sketch">Sketch to add a label to</param>
        /// <param name="substrokes">Substrokes to label</param>
        /// <param name="inkStrokes">InkOverlay strokes</param>
        /// <param name="label">Label to apply</param>
        /// <param name="labelColor">Color of the applied label</param>
        /// <param name="domainInfo">DomainInfo for our Labeler</param>
        public ApplyLabelCmd(Sketch.Sketch sketch, List <Substroke> substrokes, Microsoft.Ink.Strokes inkStrokes,
                             string label, System.Drawing.Color labelColor, DomainInfo domainInfo)
        {
            this.sketch     = sketch;
            this.substrokes = substrokes;
            this.label      = label;
            this.labelColor = labelColor;
            this.inkStrokes = inkStrokes;
            this.domainInfo = domainInfo;

            // 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>
        /// Constructor
        /// </summary>
        /// <param name="sketch">Sketch to remove a label from</param>
        /// <param name="substrokes">Substrokes that contain the label</param>
        /// <param name="inkStrokes">InkOverlay strokes</param>
        /// <param name="mIdToSubstroke">Hashtable mapping Microsoft.Ink.Stroke Ids to Sketch.Substrokes</param>
        /// <param name="label">Label to remove</param>
        /// <param name="domainInfo">DomainInfo for our Labeler</param>
        public RemoveLabelCmd(Sketch.Sketch sketch, List <Substroke> substrokes, Microsoft.Ink.Strokes inkStrokes,
                              Dictionary <int, Guid?> mIdToSubstroke, string label, DomainInfo domainInfo)
        {
            this.sketch         = sketch;
            this.substrokes     = substrokes;
            this.inkStrokes     = inkStrokes;
            this.mIdToSubstroke = mIdToSubstroke;
            this.label          = label;
            this.domainInfo     = domainInfo;

            // 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;
            }
        }
예제 #7
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();
        }
예제 #8
0
        /// <summary>
        /// Adds an Ink stroke contained within the assocated
        /// Ink object and and updates the Sketch.  Checks to ensure
        /// that the given Ink stroke is contained within Ink.
        /// </summary>
        /// <param name="id">The id of the Ink Stroke to add</param>
        public void AddInkStroke(int id)
        {
            if (ink2sketchStr.ContainsKey(id))
            {
                return;
            }

            // Try to fetch the corresponding Ink stroke
            Microsoft.Ink.Stroke iStroke;
            try
            {
                using (Microsoft.Ink.Strokes strokes = mInk.Strokes)
                {
                    if (strokes.Count == id)
                    {
                        iStroke = strokes[id - 1];
                    }
                    else
                    {
                        iStroke = strokes[strokes.Count - 1];
                    }
                }
            }
            catch (ArgumentException)
            {
                return;
                // We should never in practice get here,
                // but if we do, it means the Ink stroke
                // referenced is missing from mInk
                // !!!!!!!!! Eric 6-14-2009:
                // You will get here anytime a stroke has
                // been deleted. Added a little catch that may
                // or may not work (check if strokes.Count == id)
            }

            AddInkStroke(iStroke);
        }