Exemplo n.º 1
0
        internal static Context GetContext(Point[] pointList)
        {
            var drawingAttribute   = new DrawingAttributes();
            var strokeNodeIterator =
                StrokeNodeIterator.GetIterator(new StylusPointCollection(pointList), drawingAttribute);

            return(new Context()
            {
                StrokeNodeIterator = strokeNodeIterator,
                DrawingAttributes = drawingAttribute
            });
        }
Exemplo n.º 2
0
        /// <summary>
        /// Computes the bounds of the stroke in the default rendering context
        /// </summary>
        /// <returns></returns>
        public virtual Rect GetBounds()
        {
            if (_cachedBounds.IsEmpty)
            {
                StrokeNodeIterator iterator = StrokeNodeIterator.GetIterator(this, this.DrawingAttributes);
                for (int i = 0; i < iterator.Count; i++)
                {
                    StrokeNode strokeNode = iterator[i];
                    _cachedBounds.Union(strokeNode.GetBounds());
                }
            }

            return(_cachedBounds);
        }
Exemplo n.º 3
0
        /// <summary>Hit tests all segments within a contour generated with shape and path</summary>
        /// <param name="shape"></param>
        /// <param name="path"></param>
        /// <returns>StrokeIntersection array for these segments</returns>
        internal StrokeIntersection[] EraseTest(IEnumerable <Point> path, StylusShape shape)
        {
            System.Diagnostics.Debug.Assert(shape != null);
            System.Diagnostics.Debug.Assert(path != null);
            if (IEnumerablePointHelper.GetCount(path) == 0)
            {
                return(Array.Empty <StrokeIntersection>());
            }

            ErasingStroke             erasingStroke = new ErasingStroke(shape, path);
            List <StrokeIntersection> intersections = new List <StrokeIntersection>();

            erasingStroke.EraseTest(StrokeNodeIterator.GetIterator(this, this.DrawingAttributes), intersections);
            return(intersections.ToArray());
        }
Exemplo n.º 4
0
        public TextContext GetErasingStroke(Point[] pointList)
        {
            var erasingStroke = new ErasingStroke(new RectangleStylusShape(10, 10));

            erasingStroke.MoveTo(pointList);

            var strokeNodeIterator = StrokeNodeIterator.GetIterator(new StylusPointCollection(pointList.Select(temp => new Point(temp.X, temp.Y))),
                                                                    new DrawingAttributes()
            {
                Width  = 5,
                Height = 5
            });

            return(new TextContext(strokeNodeIterator, erasingStroke, new List <StrokeIntersection>(4096), this));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Hit tests all segments within the lasso loops
        /// </summary>
        /// <returns> a StrokeIntersection array for these segments</returns>
        internal StrokeIntersection[] HitTest(Lasso lasso)
        {
            // Check the input parameters
            System.Diagnostics.Debug.Assert(lasso != null);
            if (lasso.IsEmpty)
            {
                return(Array.Empty <StrokeIntersection>());
            }

            // The following will check whether all the points are within the lasso.
            // If yes, return the whole stroke as being hit.
            if (!lasso.Bounds.IntersectsWith(this.GetBounds()))
            {
                return(Array.Empty <StrokeIntersection>());
            }
            return(lasso.HitTest(StrokeNodeIterator.GetIterator(this, this.DrawingAttributes)));
        }
Exemplo n.º 6
0
        /// <summary>
        /// Get the Geometry of the Stroke
        /// </summary>
        /// <param name="drawingAttributes"></param>
        /// <returns></returns>
        public Geometry GetGeometry(DrawingAttributes drawingAttributes)
        {
            if (drawingAttributes == null)
            {
                throw new ArgumentNullException("drawingAttributes");
            }

            bool geometricallyEqual = DrawingAttributes.GeometricallyEqual(drawingAttributes, this.DrawingAttributes);

            // need to recalculate the PathGemetry if the DA passed in is "geometrically" different from
            // this DA, or if the cached PathGeometry is dirty.
            if (false == geometricallyEqual || (true == geometricallyEqual && null == _cachedGeometry))
            {
                //Recalculate _pathGeometry;
                StrokeNodeIterator iterator = StrokeNodeIterator.GetIterator(this, drawingAttributes);
                Geometry           geometry;
                Rect bounds;
                StrokeRenderer.CalcGeometryAndBounds(iterator,
                                                     drawingAttributes,
#if DEBUG_RENDERING_FEEDBACK
                                                     null, 0d, false,
#endif
                                                     true, //calc bounds
                                                     out geometry,
                                                     out bounds);

                // return the calculated value directly. We cannot cache the result since the DA passed in
                // is "geometrically" different from this.DrawingAttributes.
                if (false == geometricallyEqual)
                {
                    return(geometry);
                }

                // Cache the value and set _isPathGeometryDirty to false;
                SetGeometry(geometry);
                SetBounds(bounds);

                return(geometry);
            }

            // return a ref to our _cachedGeometry
            System.Diagnostics.Debug.Assert(_cachedGeometry != null && _cachedGeometry.IsFrozen);
            return(_cachedGeometry);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Issue: what's the return value
        /// </summary>
        /// <param name="path"></param>
        /// <param name="stylusShape"></param>
        /// <returns></returns>
        public StrokeCollection HitTest(IEnumerable <Point> path, StylusShape stylusShape)
        {
            // Check the input parameters
            if (stylusShape == null)
            {
                throw new System.ArgumentNullException("stylusShape");
            }
            if (path == null)
            {
                throw new System.ArgumentNullException("path");
            }
            if (IEnumerablePointHelper.GetCount(path) == 0)
            {
                return(new StrokeCollection());
            }

            // validate input
            ErasingStroke erasingStroke = new ErasingStroke(stylusShape, path);
            Rect          erasingBounds = erasingStroke.Bounds;

            if (erasingBounds.IsEmpty)
            {
                return(new StrokeCollection());
            }
            StrokeCollection hits = new StrokeCollection();

            foreach (Stroke stroke in this)
            {
                // samgeo - Presharp issue
                // Presharp gives a warning when get methods might deref a null.  It's complaining
                // here that 'stroke'' could be null, but StrokeCollection never allows nulls to be added
                // so this is not possible
#pragma warning disable 1634, 1691
#pragma warning suppress 6506
                if (erasingBounds.IntersectsWith(stroke.GetBounds()) &&
                    erasingStroke.HitTest(StrokeNodeIterator.GetIterator(stroke, stroke.DrawingAttributes)))
                {
                    hits.Add(stroke);
                }
#pragma warning restore 1634, 1691
            }

            return(hits);
        }
Exemplo n.º 8
0
        public static void CalcGeometryAndBoundsWithTransform()
        {
            var drawingAttribute   = new DrawingAttributes();
            var strokeNodeIterator = StrokeNodeIterator.GetIterator(new StylusPointCollection(new Point[]
            {
                new Point(10, 10),
                new Point(11, 10),
                new Point(12, 10),
                new Point(13, 10),
                new Point(14, 10),
                new Point(15, 10),
                new Point(15, 11),
                new Point(15, 12),
                new Point(15, 13),
                new Point(15, 14),
                new Point(15, 15),
                new Point(25, 35),
                new Point(35, 15),
                new Point(55, 25),
            }), drawingAttribute);

            StrokeRenderer.CalcGeometryAndBoundsWithTransform(strokeNodeIterator, drawingAttribute,
                                                              MatrixTypes.TRANSFORM_IS_IDENTITY, true, out var geometry, out var bounds);
        }
Exemplo n.º 9
0
        /// <summary>
        /// The core functionality to draw a stroke. The function can be called from the following code paths.
        ///     i) From StrokeVisual.OnRender
        ///         a. Highlighter strokes have been grouped and the correct opacity has been set on the container visual.
        ///         b. For a highlighter stroke with color.A != 255, the DA passed in is a copy with color.A set to 255.
        ///         c. _drawAsHollow can be true, i.e., Selected stroke is drawn as hollow
        ///     ii) From StrokeCollection.Draw.
        ///         a. Highlighter strokes have been grouped and the correct opacity has been pushed.
        ///         b. For a highlighter stroke with color.A != 255, the DA passed in is a copy with color.A set to 255.
        ///         c. _drawAsHollow is always false, i.e., Selected stroke is not drawn as hollow
        ///     iii) From Stroke.Draw
        ///         a. The correct opacity has been pushed for a highlighter stroke
        ///         b. For a highlighter stroke with color.A != 255, the DA passed in is a copy with color.A set to 255.
        ///         c. _drawAsHollow is always false, i.e., Selected stroke is not drawn as hollow
        /// We need to document the following:
        /// 1) our default implementation so developers can see what we've done here -
        ///    including how we handle IsHollow
        /// 2) the fact that opacity has already been set up correctly for the call.
        /// 3) that developers should not call base.DrawCore if they override this
        /// </summary>
        /// <param name="drawingContext">DrawingContext to draw on</param>
        /// <param name="drawingAttributes">DrawingAttributes to draw with</param>
        protected virtual void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes)
        {
            if (null == drawingContext)
            {
                throw new System.ArgumentNullException("drawingContext");
            }

            if (null == drawingAttributes)
            {
                throw new System.ArgumentNullException("drawingAttributes");
            }

            if (_drawAsHollow == true)
            {
                // Draw as hollow. Our profiler result shows that the two-pass-rendering approach is about 5 times
                // faster that using GetOutlinePathGeometry.
                // also, the minimum display size for selected ink is our default width / height

                Matrix            innerTransform, outerTransform;
                DrawingAttributes selectedDA = drawingAttributes.Clone();
                selectedDA.Height = Math.Max(selectedDA.Height, DrawingAttributes.DefaultHeight);
                selectedDA.Width  = Math.Max(selectedDA.Width, DrawingAttributes.DefaultWidth);
                CalcHollowTransforms(selectedDA, out innerTransform, out outerTransform);

                // First pass drawing. Use drawingAttributes.Color to create a solid color brush. The stroke will be drawn as
                // 1 avalon-unit higher and wider (HollowLineSize = 1.0f)
                selectedDA.StylusTipTransform = outerTransform;
                SolidColorBrush brush = new SolidColorBrush(drawingAttributes.Color);
                brush.Freeze();
                drawingContext.DrawGeometry(brush, null, GetGeometry(selectedDA));

                //Second pass drawing with a white color brush. The stroke will be drawn as
                // 1 avalon-unit shorter and narrower (HollowLineSize = 1.0f) if the actual-width/height (considering StylusTipTransform)
                // is larger than HollowLineSize. Otherwise the same size stroke is drawn.
                selectedDA.StylusTipTransform = innerTransform;
                drawingContext.DrawGeometry(Brushes.White, null, GetGeometry(selectedDA));
            }
            else
            {
#if DEBUG_RENDERING_FEEDBACK
                //render debug feedback?
                Guid guid = new Guid("52053C24-CBDD-4547-AAA1-DEFEBF7FD1E1");
                if (this.ContainsPropertyData(guid))
                {
                    double thickness = (double)this.GetPropertyData(guid);

                    //first, draw the outline of the stroke
                    drawingContext.DrawGeometry(null,
                                                new Pen(Brushes.Black, thickness),
                                                GetGeometry());

                    Geometry g2;
                    Rect     b2;
                    //next, overlay the connecting quad points
                    StrokeRenderer.CalcGeometryAndBounds(StrokeNodeIterator.GetIterator(this, drawingAttributes),
                                                         drawingAttributes,
                                                         drawingContext, thickness, true,
                                                         true, //calc bounds
                                                         out g2,
                                                         out b2);
                }
                else
                {
#endif
                SolidColorBrush brush = new SolidColorBrush(drawingAttributes.Color);
                brush.Freeze();
                drawingContext.DrawGeometry(brush, null, GetGeometry(drawingAttributes));
#if DEBUG_RENDERING_FEEDBACK
            }
#endif
            }
        }