Пример #1
0
        /// <summary>Slices off anything below the given line.</summary>
        public override void SliceBottom(float sliceLine, VectorPath path)
        {
            float previous = Previous.Y;
            float current  = Y;

            // Both below?
            if (previous < sliceLine && current < sliceLine)
            {
                // Both below.
                path.RemoveVisually(this);

                return;
            }
            else if (previous >= sliceLine && current >= sliceLine)
            {
                // Do nothing.
                return;
            }

            // Split where the slice line is.
            VectorPoint newPoint = Split((sliceLine - previous) / (current - previous), path);

            // Delete the segment to the left/right.
            if (current < sliceLine)
            {
                // Delete this -> newPoint
                path.RemoveVisually(newPoint);
            }
            else
            {
                // Delete previous -> this
                path.RemoveVisually(this);
            }
        }
		public override VectorPoint Split(float t,VectorPath path){
			
			// Create the next one:
			StraightLinePoint point=new StraightLinePoint(X,Y);
			
			// Get previous:
			float previousX=Previous.X;
			float previousY=Previous.Y;
			
			// Get deltas:
			float dx=X-previousX;
			float dy=Y-previousY;
			
			float nX=previousX + (t*dx);
			float nY=previousY + (t*dy);
			
			X=nX;
			Y=nY;
			
			path.PathNodeCount++;
			
			// Insert after this:
			if(Next==null){
				path.LatestPathNode=point;
			}else{
				point.Next=Next;
				Next.Previous=point;
			}
			
			point.Previous=this;
			Next=point;
			
			return point;
		}
        public override void RecalculateBounds(VectorPath path)
        {
            // Take control point into account too:
            if (Control2X < path.MinX)
            {
                path.MinX = Control2X;
            }

            if (Control2Y < path.MinY)
            {
                path.MinY = Control2Y;
            }

            // Width/height are used as max to save some memory:
            if (Control2X > path.Width)
            {
                path.Width = Control2X;
            }

            if (Control2Y > path.Height)
            {
                path.Height = Control2Y;
            }

            base.RecalculateBounds(path);
        }
Пример #4
0
        /// <summary>Replaces this point with another.</summary>
        public void ReplaceWith(VectorPoint replacement, VectorPath path)
        {
            if (replacement == null)
            {
                return;
            }

            // Update next/prev:
            replacement.Next     = Next;
            replacement.Previous = Previous;
            replacement.IsClose  = IsClose;

            if (Next == null)
            {
                path.LatestPathNode = replacement;
            }
            else
            {
                Next.Previous = replacement;
            }

            if (Previous == null)
            {
                path.FirstPathNode = replacement;
            }
            else
            {
                Previous.Next = replacement;
            }
        }
Пример #5
0
        public override void RecalculateBounds(VectorPath path)
        {
            // Take control point into account too:
            if (CenterX < path.MinX)
            {
                path.MinX = CenterX;
            }

            if (CenterY < path.MinY)
            {
                path.MinY = CenterY;
            }

            // Width/height are used as max to save some memory:
            if (CenterX > path.Width)
            {
                path.Width = CenterX;
            }

            if (CenterY > path.Height)
            {
                path.Height = CenterY;
            }

            // Proportion of the overall length (0-1):
            float lengthPortion = SweepAngle / 2f * (float)Math.PI;

            // Approximate ellipse length:
            float h = (float)(Math.Pow((RadiusX - RadiusY), 2f) / Math.Pow((RadiusX + RadiusY), 2f));

            Length = lengthPortion * (((float)Math.PI * (RadiusX + RadiusY)) *
                                      (1f + ((3f * h) / (10f + (float)Math.Sqrt(4f - (3f * h))))));

            base.RecalculateBounds(path);
        }
		public override void RecalculateBounds(VectorPath path){
			
			// Take control point into account too:
			if(CircleCenterX<path.MinX){
				path.MinX=CircleCenterX;
			}
			
			if(CircleCenterY<path.MinY){
				path.MinY=CircleCenterY;
			}
			
			// Width/height are used as max to save some memory:
			if(CircleCenterX>path.Width){
				path.Width=CircleCenterX;
			}
			
			if(CircleCenterY>path.Height){
				path.Height=CircleCenterY;
			}
			
			// How much must we rotate through overall?
			float angleToRotateThrough=EndAngle-StartAngle;
			
			// How long is the arc?
			// First, what portion of a full circle is it:
			float circlePortion=angleToRotateThrough/((float)Math.PI*2f);
			
			// Next, what's the circumference of that circle
			// (and the above portion of it, thus the length of the arc):
			Length=2f*(float)Math.PI*Radius * circlePortion;
			
			base.RecalculateBounds(path);
			
		}
Пример #7
0
        public override void ExtrudeAndSample(VectorPath path, float extrudeBy, PointReceiverStepped sampler)
        {
            // Cache radius:
            float radius = Radius;

            // Extrude:
            Radius += extrudeBy;

            // Clamp:
            if (Radius < 0f)
            {
                Radius = 0f;
            }

            // Rebound:
            RecalculateBounds(path);

            if (sampler.IncludeFirstNode)
            {
                sampler.AddPoint(Previous.X, Previous.Y, 0f);
            }

            // Sample now:
            ComputeLinePoints(sampler);

            // Restore:
            Radius = radius;
        }
		public override void RecalculateBounds(VectorPath path){
			
			// Take control point into account too:
			if(Control1X<path.MinX){
				path.MinX=Control1X;
			}
			
			if(Control1Y<path.MinY){
				path.MinY=Control1Y;
			}
			
			// Width/height are used as max to save some memory:
			if(Control1X>path.Width){
				path.Width=Control1X;
			}
			
			if(Control1Y>path.Height){
				path.Height=Control1Y;
			}
			
			// Start figuring out the length..
			float vaX=Previous.X-(2f*Control1X)+X;
			float vaY=Previous.Y-(2f*Control1Y)+Y;
			
			float vbX=(2f*Control1X) - (2f*Previous.X);
			float vbY=(2f*Control1Y) - (2f*Previous.Y);
			
			float a=4f*((vaX*vaX) + (vaY*vaY));
			
			float b=4f*((vaX*vbX) + (vaY*vbY));
			
			float c=(vbX*vbX) + (vbY*vbY);
			
			float rootABC = 2f*(float)Math.Sqrt(a+b+c);
			float rootA = (float)Math.Sqrt(a);
			float aRootA = 2f*a*rootA;
			
			if(aRootA==0f){
				
				Length=0f;
				
			}else{
				
				float rootC = 2f*(float)Math.Sqrt(c);
				float bA = b/rootA;
				
				Length=(
					aRootA * rootABC + rootA*b*(rootABC-rootC) + (4f*c*a - b*b)*(float)Math.Log(
						(2f*rootA+bA+rootABC) / (bA+rootC)
					)
				) / (4f*aRootA);
			
			}
			
			base.RecalculateBounds(path);
			
		}
Пример #9
0
        public override void ExtrudeAndSample(VectorPath path, float extrudeBy, PointReceiverStepped sampler)
        {
            // First, cache all the points:
            float prevX = Previous.X;
            float prevY = Previous.Y;
            float c1x   = Control1X;
            float c1y   = Control1Y;
            float c2x   = Control2X;
            float c2y   = Control2Y;
            float x     = X;
            float y     = Y;

            // Get the normals and extrude along them.
            float normalX;
            float normalY;

            // First point:
            StartNormal(out normalX, out normalY);
            Previous.X += normalX * extrudeBy;
            Previous.Y += normalY * extrudeBy;

            // First control:
            NormalAt(0.3333f, out normalX, out normalY);
            Control1X += normalX * extrudeBy;
            Control1Y += normalY * extrudeBy;

            // Second control:
            NormalAt(0.6666f, out normalX, out normalY);
            Control2X += normalX * extrudeBy;
            Control2Y += normalY * extrudeBy;

            // Last point:
            EndNormal(out normalX, out normalY);
            X += normalX * extrudeBy;
            Y += normalY * extrudeBy;

            // Rebound:
            RecalculateBounds(path);

            if (sampler.IncludeFirstNode)
            {
                sampler.AddPoint(Previous.X, Previous.Y, 0f);
            }

            // Sample now:
            ComputeLinePoints(sampler);

            // Restore all the points:
            Previous.X = prevX;
            Previous.Y = prevY;
            Control1X  = c1x;
            Control1Y  = c1y;
            Control2X  = c2x;
            Control2Y  = c2y;
            X          = x;
            Y          = y;
        }
Пример #10
0
        public override VectorPoint DeleteControl(int id, VectorPath path)
        {
            // Create:
            VectorPoint pt = new StraightLinePoint(X, Y);

            // Remove this and add in it's place:
            ReplaceWith(pt, path);

            return(pt);
        }
Пример #11
0
        /// <summary>Copies this path.</summary>
        public VectorPath CopyPath()
        {
            // Create:
            VectorPath path = new VectorPath();

            // Copy into it:
            CopyInto(path);

            return(path);
        }
Пример #12
0
        /// <summary>Simplifies this path now using the given midpoint of the line.</summary>
        internal void SimplifyNow(VectorPath path)
        {
            // Split down the middle, then do it again on those two sublines.
            Split(0.5f, path);

            // Split 2nd half:
            Next.Split(0.5f, path);

            // Split 1st half (this object again):
            Split(0.5f, path);
        }
Пример #13
0
        public override void RecalculateBounds(VectorPath path)
        {
            // Get deltas:
            float dx = X - Previous.X;
            float dy = Y - Previous.Y;

            // Length:
            Length = (float)Math.Sqrt((dx * dx) + (dy * dy));

            base.RecalculateBounds(path);
        }
		public override void RecalculateBounds(VectorPath path){
			
			// Get deltas:
			float dx=X-Previous.X;
			float dy=Y-Previous.Y;
			
			// Length:
			Length=(float)Math.Sqrt((dx*dx)+(dy*dy));
			
			base.RecalculateBounds(path);
			
		}
Пример #15
0
        /// <summary>Copies a section of this path.
        /// Note that if p2 is before p1, it will safely loop over a closed node.
        /// </summary>
        public VectorPath CopySection(VectorPoint p1, float c1, VectorPoint p2, float c2)
        {
            // Split the line p1 at c1.
            // Split the line p2 at c2.
            // The section between these two nodes is the part we want.

            // Create the path:
            VectorPath path = new VectorPath();

            if (p1 == null)
            {
                p1 = FirstPathNode;
                c1 = 0f;
            }

            // Add the first node:
            path.AddPathNode(p1.PointAt(c1, true));

            VectorPoint current = p1.Next;

            while (current != p2 && current != null)
            {
                if (current == p1)
                {
                    // This occurs when p1 and p2 are not in the same shape.
                    throw new Exception("Section start and end are not from the same path.");
                }

                // Add a copy:
                path.AddPathNode(current.Copy());

                // Go to next:
                current = current.Next;

                if (current == null && p2 != null)
                {
                    // Need to loop back around unless p2 is null.
                    // Notice that we actively skip the moveTo itself as
                    // current is in the same location.
                    current = path.FirstPathNode.Next;
                }
            }

            if (current == p2 && p2 != null)
            {
                // Add it:
                path.AddPathNode(p2.PointAt(c2, false));
            }

            return(path);
        }
		public override VectorPoint Split(float t,VectorPath path){
			
			float invert=1f-t;
			
			float p0x=Previous.X;
			float p0y=Previous.Y;
			
			float p1x=Control1X;
			float p1y=Control1Y;
			
			float p2x=X;
			float p2y=Y;
			
			// The new points:
			float p3x=p0x * invert + p1x * t;
			float p3y=p0y * invert + p1y * t;
			
			float p4x=p1x * invert + p2x * t;
			float p4y=p1y * invert + p2y * t;
			
			float p5x=p3x * invert + p4x * t;
			float p5y=p3y * invert + p4y * t;
			
			// This curve will become the new 1st half:
			Control1X=p3x;
			Control1Y=p3y;
			
			X=p5x;
			Y=p5y;
			
			path.PathNodeCount++;
			
			// Create the next one:
			QuadLinePoint point=new QuadLinePoint(p2x,p2y);
			
			point.Control1X=p4x;
			point.Control1Y=p4y;
			
			// Insert after this:
			if(Next==null){
				path.LatestPathNode=point;
			}else{
				point.Next=Next;
				Next.Previous=point;
			}
			
			point.Previous=this;
			Next=point;
			
			return point;
		}
Пример #17
0
        public override VectorPoint AddControl(float x, float y, VectorPath path, out int id)
        {
            id = 0;

            // Just split the line:

            // Get the "progress" of x/y along the line:
            float C      = X - Previous.X;
            float D      = Y - Previous.Y;
            float len_sq = C * C + D * D;
            float t      = ProgressAlongFast(x, y, C, D, len_sq);

            return(Split(t, path));
        }
Пример #18
0
        public override VectorPoint AddControl(float x, float y, VectorPath path, out int id)
        {
            // Create:
            QuadLinePoint pt = new QuadLinePoint(X, Y);

            pt.Control1X = x;
            pt.Control1Y = y;

            // Remove this and add pt in it's place:
            ReplaceWith(pt, path);

            id = 1;

            return(pt);
        }
Пример #19
0
        public override VectorPoint Split(float t, VectorPath path)
        {
            // Create the next one:
            StraightLinePoint point = new StraightLinePoint(X, Y);

            // Get previous:
            float previousX = Previous.X;
            float previousY = Previous.Y;

            // Get deltas:
            float dx = X - previousX;
            float dy = Y - previousY;

            float nX = previousX + (t * dx);
            float nY = previousY + (t * dy);

            X = nX;
            Y = nY;

            path.PathNodeCount++;

            // Insert after this:
            if (Next == null)
            {
                path.LatestPathNode = point;
            }
            else
            {
                point.Next    = Next;
                Next.Previous = point;
            }

            // Update lengths:
            point.Length = (1f - t) * Length;
            Length       = t * Length;

            point.Previous = this;
            Next           = point;

            if (IsClose)
            {
                IsClose                   = false;
                point.IsClose             = true;
                path.CloseNode.ClosePoint = point;
            }

            return(point);
        }
Пример #20
0
        public override void RecalculateBounds(VectorPath path)
        {
            // Take control point into account too:
            if (Control2X < path.MinX)
            {
                path.MinX = Control2X;
            }

            if (Control2Y < path.MinY)
            {
                path.MinY = Control2Y;
            }

            // Width/height are used as max to save some memory:
            if (Control2X > path.Width)
            {
                path.Width = Control2X;
            }

            if (Control2Y > path.Height)
            {
                path.Height = Control2Y;
            }

            // Start figuring out the length (very approximate)..

            float dx = Previous.X - Control1X;
            float dy = Previous.Y - Control1Y;

            double len = Math.Sqrt(dx * dx + dy * dy);

            dx = Control2X - Control1X;
            dy = Control2Y - Control1Y;

            len += Math.Sqrt(dx * dx + dy * dy);

            dx = X - Control2X;
            dy = Y - Control2Y;

            len += Math.Sqrt(dx * dx + dy * dy);

            Length = (float)len;

            BaseBounds(path);
        }
Пример #21
0
        public override VectorPoint AddControl(float x, float y, VectorPath path, out int id)
        {
            // Create:
            CurveLinePoint pt = new CurveLinePoint(X, Y);

            // Get the "progress" of x/y along the line, vs control point progress.
            float C      = X - Previous.X;
            float D      = Y - Previous.Y;
            float len_sq = C * C + D * D;

            float newProg = ProgressAlongFast(x, y, C, D, len_sq);
            float p1Prog  = ProgressAlongFast(Control1X, Control1Y, C, D, len_sq);

            // Should this new control be control point #1?
            bool first = (newProg < p1Prog);

            if (first)
            {
                // Pt 1:
                pt.Control1X = x;
                pt.Control1Y = y;

                pt.Control2X = Control1X;
                pt.Control2Y = Control1Y;

                id = 1;
            }
            else
            {
                // Pt 2:
                pt.Control1X = Control1X;
                pt.Control1Y = Control1Y;

                pt.Control2X = x;
                pt.Control2Y = y;

                id = 2;
            }

            // Remove this and add in it's place:
            ReplaceWith(pt, path);

            return(pt);
        }
Пример #22
0
        public override VectorPath GetPath(RenderableData context, CssProperty property)
        {
            if (CachedPath_ == null)
            {
                CachedPath_ = new VectorPath();

                // Create the curve now:
                CachedPath_.CurveTo(

                    this[0].GetDecimal(context, property),
                    this[1].GetDecimal(context, property),
                    this[2].GetDecimal(context, property),
                    this[3].GetDecimal(context, property),
                    1f, 1f

                    );
            }

            return(CachedPath_);
        }
Пример #23
0
        /// <summary>Copies this vector path into the given one.</summary>
        public void CopyInto(VectorPath path)
        {
            VectorPoint point = FirstPathNode;

            while (point != null)
            {
                VectorPoint copiedPoint = point.Copy();

                path.AddPathNode(copiedPoint);

                // Copy close status:
                if (point.IsClose)
                {
                    copiedPoint.IsClose       = true;
                    path.CloseNode.ClosePoint = copiedPoint;
                }

                point = point.Next;
            }
        }
Пример #24
0
        /// <summary>Adds the given path onto the end of this one.</summary>
        public void Append(VectorPath path)
        {
            if (LatestPathNode == null)
            {
                // This path just becomes the same as the given one:
                FirstPathNode  = path.FirstPathNode;
                LatestPathNode = path.LatestPathNode;
                PathNodeCount  = path.PathNodeCount;
                CloseNode      = path.CloseNode;
            }
            else
            {
                // Add the first node:
                AddPathNode(path.FirstPathNode);
                LatestPathNode = path.LatestPathNode;

                // -1 because Add already added the first node.
                PathNodeCount += path.PathNodeCount - 1;

                CloseNode = path.CloseNode;
            }
        }
		public override void RecalculateBounds(VectorPath path){
			
			// Take control point into account too:
			if(Control2X<path.MinX){
				path.MinX=Control2X;
			}
			
			if(Control2Y<path.MinY){
				path.MinY=Control2Y;
			}
			
			// Width/height are used as max to save some memory:
			if(Control2X>path.Width){
				path.Width=Control2X;
			}
			
			if(Control2Y>path.Height){
				path.Height=Control2Y;
			}
			
			base.RecalculateBounds(path);
			
		}
Пример #26
0
        public override VectorPoint DeleteControl(int id, VectorPath path)
        {
            // Create:
            QuadLinePoint pt = new QuadLinePoint(X, Y);

            if (id == 1)
            {
                // Deleting control point 1.
                pt.Control1X = Control2X;
                pt.Control1Y = Control2Y;
            }
            else
            {
                // Deleting control point 2.
                pt.Control1X = Control1X;
                pt.Control1Y = Control1Y;
            }

            // Remove this and add in it's place:
            ReplaceWith(pt, path);

            return(pt);
        }
Пример #27
0
        /// <summary>Recalculates the minimum values and width/height of this path, taking curves into account.</summary>
        public virtual void RecalculateBounds(VectorPath path)
        {
            if (X < path.MinX)
            {
                path.MinX = X;
            }

            if (Y < path.MinY)
            {
                path.MinY = Y;
            }

            // Width/height are used as max to save some memory:
            if (X > path.Width)
            {
                path.Width = X;
            }

            if (Y > path.Height)
            {
                path.Height = Y;
            }
        }
        public override void RecalculateBounds(VectorPath path)
        {
            // Take control point into account too:
            if (CircleCenterX < path.MinX)
            {
                path.MinX = CircleCenterX;
            }

            if (CircleCenterY < path.MinY)
            {
                path.MinY = CircleCenterY;
            }

            // Width/height are used as max to save some memory:
            if (CircleCenterX > path.Width)
            {
                path.Width = CircleCenterX;
            }

            if (CircleCenterY > path.Height)
            {
                path.Height = CircleCenterY;
            }

            // How much must we rotate through overall?
            float angleToRotateThrough = EndAngle - StartAngle;

            // How long is the arc?
            // First, what portion of a full circle is it:
            float circlePortion = angleToRotateThrough / ((float)Math.PI * 2f);

            // Next, what's the circumference of that circle
            // (and the above portion of it, thus the length of the arc):
            Length = 2f * (float)Math.PI * Radius * circlePortion;

            base.RecalculateBounds(path);
        }
        public override VectorPoint Split(float t, VectorPath path)
        {
            // Create the next one:
            StraightLinePoint point = new StraightLinePoint(X, Y);

            // Get previous:
            float previousX = Previous.X;
            float previousY = Previous.Y;

            // Get deltas:
            float dx = X - previousX;
            float dy = Y - previousY;

            float nX = previousX + (t * dx);
            float nY = previousY + (t * dy);

            X = nX;
            Y = nY;

            path.PathNodeCount++;

            // Insert after this:
            if (Next == null)
            {
                path.LatestPathNode = point;
            }
            else
            {
                point.Next    = Next;
                Next.Previous = point;
            }

            point.Previous = this;
            Next           = point;

            return(point);
        }
Пример #30
0
        public override void ExtrudeAndSample(VectorPath path, float extrudeBy, PointReceiverStepped sampler)
        {
            // First, cache all the points:
            float prevX = Previous.X;
            float prevY = Previous.Y;
            float x     = X;
            float y     = Y;

            // Get the normal and extrude along it.
            float normalX;
            float normalY;

            StartNormal(out normalX, out normalY);

            Previous.X += normalX * extrudeBy;
            Previous.Y += normalY * extrudeBy;
            X          += normalX * extrudeBy;
            Y          += normalY * extrudeBy;

            // Rebound:
            RecalculateBounds(path);

            if (sampler.IncludeFirstNode)
            {
                sampler.AddPoint(Previous.X, Previous.Y, 0f);
            }

            // Sample now:
            ComputeLinePoints(sampler);

            // Restore all the points:
            Previous.X = prevX;
            Previous.Y = prevY;
            X          = x;
            Y          = y;
        }
Пример #31
0
        /// <summary>Requests to draw the given path at the given atlas location.</summary>
        public static void RequestDraw(AtlasLocation location, VectorPath path, float offsetX, float offsetY, float drawHeight)
        {
            DrawingTexture drawing = new DrawingTexture();

            drawing.Location = location;
            drawing.Path     = path;
            drawing.OffsetX  = offsetX;
            drawing.OffsetY  = offsetY;

            if (Camera == null)
            {
                Camera = new TextureCamera(CPUCopyMode);

                // Apply scale:
                Scale = drawHeight * Camera.WorldPerPixel.x;
            }

            if (Camera.IsDrawing || !Camera.TryFit(drawing))
            {
                // Add to global pending queue:
                drawing.NextDrawing = Pending;
                Pending             = drawing;
            }
        }
Пример #32
0
        public override void RecalculateBounds(VectorPath path)
        {
            // Take control point into account too:
            if (Control1X < path.MinX)
            {
                path.MinX = Control1X;
            }

            if (Control1Y < path.MinY)
            {
                path.MinY = Control1Y;
            }

            // Width/height are used as max to save some memory:
            if (Control1X > path.Width)
            {
                path.Width = Control1X;
            }

            if (Control1Y > path.Height)
            {
                path.Height = Control1Y;
            }

            /*
             * // Start figuring out the length..
             * float vaX=Previous.X-(2f*Control1X)+X;
             * float vaY=Previous.Y-(2f*Control1Y)+Y;
             *
             * float vbX=(2f*Control1X) - (2f*Previous.X);
             * float vbY=(2f*Control1Y) - (2f*Previous.Y);
             *
             * float a=4f*((vaX*vaX) + (vaY*vaY));
             *
             * float b=4f*((vaX*vbX) + (vaY*vbY));
             *
             * float c=(vbX*vbX) + (vbY*vbY);
             *
             * float rootABC = 2f*(float)Math.Sqrt(a+b+c);
             * float rootA = (float)Math.Sqrt(a);
             * float aRootA = 2f*a*rootA;
             *
             * if(aRootA==0f){
             *
             *      Length=0f;
             *
             * }else{
             *
             *      float rootC = 2f*(float)Math.Sqrt(c);
             *      float bA = b/rootA;
             *
             *      Length=(
             *              aRootA * rootABC + rootA*b*(rootABC-rootC) + (4f*c*a - b*b)*(float)Math.Log(
             *                      (2f*rootA+bA+rootABC) / (bA+rootC)
             *              )
             *      ) / (4f*aRootA);
             *
             * }
             */

            // Start figuring out the length (very approximate)..

            float dx = Previous.X - Control1X;
            float dy = Previous.Y - Control1Y;

            double len = Math.Sqrt(dx * dx + dy * dy);

            dx = X - Control1X;
            dy = Y - Control1Y;

            len += Math.Sqrt(dx * dx + dy * dy);

            Length = (float)len;

            base.RecalculateBounds(path);
        }
//--------------------------------------
Пример #34
0
 public void BaseBounds(VectorPath path)
 {
     base.RecalculateBounds(path);
 }
Пример #35
0
//--------------------------------------
Пример #36
0
		/// <summary>Rasterises a generic vector.</summary>
		public bool Rasterise(VectorPath glyph,Color32[] atlasPixels,int atlasWidth,int baseIndex,int width,int height,float hOffset,float vOffset,Color32 fill,bool clear){
			
			if(glyph.FirstPathNode==null){
				return false;
			}
			
			if(RequiresStart){
				// Start now:
				Start();
			}
			
			PreviousY=-1;
			
			// Offset the rasteriser:
			VerticalOffset=vOffset;
			HorizontalOffset=hOffset;
			
			
			if(Blurred){
				
				// Add some space for the blur:
				width+=BlurSpread;
				height+=BlurSpread;
				
			}
			
			if(clear){
				int atlasIndex=baseIndex;
				
				for(int i=0;i<height;i++){
					
					// Clear the row:
					Array.Clear(atlasPixels,atlasIndex,width);
					
					atlasIndex+=atlasWidth;
					
				}
				
			}
			
			if(Blurred){
				
				if( width > (DistanceCacheWidth * BlurSpread) ){
					
					// Resize time!
					DistanceCacheWidth = ((width-1)/BlurSpread)+1;
					
					// Rebuild:
					CreateDistanceCache();
					
				}else if(height > (DistanceCacheHeight * BlurSpread)){
					
					// Resize time!
					DistanceCacheHeight = ((height-1)/BlurSpread)+1;
					
					// Rebuild:
					CreateDistanceCache();
					
				}else{
					
					// Clear the cache:
					ClearDistanceCache();
					
				}
				
			}
			
			if(ScanLineBuffer==null || ScanLineBuffer.Length<=height){
				
				// Create the shared buffer:
				ScanLineBuffer=new ScannerScanLine[height+1];
				
			}
			
			// Clear the buffer:
			for(int i=0;i<=height;i++){
				
				// Grab the line:
				ScannerScanLine line=ScanLineBuffer[i];
				
				if(line==null){
					
					// Create it now:
					ScanLineBuffer[i]=new ScannerScanLine(this);
					
					continue;
					
				}
				
				// Empty the line (into the pool):
				line.Clear();
				
			}
			
			// For each line in the glyph, resolve it into a series of points.
			// Each one is at most one pixel away from the previous point.
			
			// Get the next point (exists due to check above):
			VectorPoint point=glyph.FirstPathNode;
			
			while(point!=null){
				
				// Compute the points along the line which are fairly dense and regularly spaced (when possible):
				point.ComputeLinePoints(this);
				
				if((point.IsClose || point.Next==null) && LineChangeY!=-1 && MoveToY==-1){
					// Test if we need to add our special point:
					
					if(LineChangeWentUp!=WentUp){
						
						if(LineChangeY>=0 && LineChangeY<ScanLineBuffer.Length){
							AddPixel(LineChangeX,LineChangeY);
						}
						
					}
					
					// Clear Y:
					LineChangeY=-1;
				}
				
				// Go to the next one:
				point=point.Next;
				
			}
			
			int blurOffset=HalfBlurSpread;
			
			// For each scan line, skipping the ones we know won't contain anything at this point:
			int verticalMax=height-blurOffset;
			
			// Stop only one blurspread from the end - we know there's nothing beyond that.
			int lineMax=width-blurOffset;
			
			// The current pixel index - offset over the blur spread:
			int pixelIndex=baseIndex + (atlasWidth * blurOffset);
			
			if(Blurred){
				
				// SDF mode
				
				for(int i=blurOffset;i<verticalMax;i++){
					
					// Grab the line:
					ScannerScanLine line=ScanLineBuffer[i];
					
					if(line.First==null){
						
						// Advance to the next line:
						pixelIndex+=atlasWidth;
						
						continue;
						
					}
					
					// Grab the first pixel (each one represents an intersect):
					ScannerPixel inwardPixel=line.First;
					
					while(inwardPixel!=null){
						
						// Grab the next one:
						ScannerPixel outwardPixel=inwardPixel.Next;
						
						
						if(outwardPixel==null){
							break;
						}
						
						// Index of the last pixel (exclusive):
						int max=outwardPixel.PixelIndex;
						
						if(max>lineMax){
							// Clip it:
							max=lineMax;
						}
						
						// The section from inwardPixel to outwardPixel is filled.
						
						for(int p=inwardPixel.PixelIndex;p<max;p++){
							
							// Fill:
							atlasPixels[pixelIndex+p]=fill;
							
						}
						
						if(outwardPixel==null){
							
							// No more pairs:
							break;
							
						}
						
						// Go to the next intersect:
						inwardPixel=outwardPixel.Next;
						
					}
					
					// Advance to the next line:
					pixelIndex+=atlasWidth;
					
				}
				
				// "blur" time!
				
				int cacheSquareIndex=0;
				int blurSpread=BlurSpread;
				int atlasSize=atlasPixels.Length;
				
				// For each distance cache square..
				for(int dY=0;dY<DistanceCacheHeight;dY++){
					
					for(int dX=0;dX<DistanceCacheWidth;dX++){
						
						// Get the square:
						DistanceCacheSquare currentSquare=DistanceCache[cacheSquareIndex];
						
						pixelIndex=baseIndex+(currentSquare.PixelIndexY * atlasWidth)+currentSquare.PixelIndexX;
						
						if(currentSquare.InRange){
							
							// Get the FX/FY:
							float squareFX=currentSquare.XOffset;
							
							float fY=currentSquare.YOffset;
							float fX=squareFX;
							
							// Grab the squares search set:
							DistanceCacheSquare[] toSearch=currentSquare.SearchSet;
							
							// How many?
							int searchCount=toSearch.Length;
							
							// Reset pixel index:
							pixelIndex=baseIndex+(currentSquare.PixelIndexY * atlasWidth)+currentSquare.PixelIndexX;
							
							// For each pixel in this square..
							for(int y=0;y<blurSpread;y++){
								
								if(pixelIndex>=atlasSize){
									break;
								}
								
								for(int x=0;x<blurSpread;x++){
									
									// Where's the pixel?
									int fullIndex=pixelIndex+x;
									
									if(fullIndex>=atlasSize){
										break;
									}
									
									// Must be black otherwise we'll ignore it.
									if(atlasPixels[fullIndex].r!=0){
										
										// It has colour. Skip.
										
										// Move float x along:
										fX++;
										
										continue;
										
									}
									
									// Start doing distance tests - look in all the nearest squares:
									float bestDistance=float.MaxValue;
									
									for(int i=0;i<searchCount;i++){
										
										DistanceCacheSquare square=toSearch[i];
										
										if(square.Count==0){
											// Ignore empty square.
											continue;
										}
										
										// Temp grab the point set:
										List<DistanceCachePoint> points=square.Points;
										
										// How many points?
										int pointCount=points.Count;
										
										// For each node in the square, find the (relative) nearest.
										for(int p=0;p<pointCount;p++){
											
											// Get the point:
											DistanceCachePoint cachePoint=points[p];
											
											// Distance check:
											float deltaX=cachePoint.X - fX;
											
											float deltaY=cachePoint.Y - fY;
											
											// Full distance:
											float distance=(deltaX * deltaX) + (deltaY * deltaY);
											
											if(distance<bestDistance){
												
												// Closest distance found:
												bestDistance=distance;
												
											}
											
										}
										
									}
									
									// Result value:
									byte distancePixel;
									
									if(bestDistance>MaxDistanceSquared){
										
										// The pixel should be black:
										distancePixel=0;
										
									}else{
										
										// Map the distance to an accurate distance, and put it in range:
										distancePixel=(byte)(255f-(Math.Sqrt(bestDistance) * DistanceAdjuster));
										
									}
									
									// Write the result:
									atlasPixels[fullIndex]=new Color32(fill.r,fill.g,fill.b,distancePixel);
									
									// Move float x along:
									fX++;
									
								}
								
								// Move float y along:
								fY++;
								fX=squareFX;
								
								// Move pixel index up a row:
								pixelIndex+=atlasWidth;
								
							}
							
						}
						
						cacheSquareIndex++;
						
					}
					
				}
				
			}else{
				
				// Got alpha?
				bool fillAlpha=(fill.a!=255 && !clear);

				// "Invert" fill alpha:
				int alphaInvert=255-fill.a;
				int fillRA=fill.r * fill.a;
				int fillGA=fill.g * fill.a;
				int fillBA=fill.b * fill.a;
				
				
				for(int i=blurOffset;i<verticalMax;i++){
					
					// Grab the line:
					ScannerScanLine line=ScanLineBuffer[i];
					
					if(line.First==null){
						
						// Advance to the next line:
						pixelIndex+=atlasWidth;
						
						continue;
						
					}
					
					// Grab the first pixel (each one represents an intersect):
					ScannerPixel inwardPixel=line.First;
					
					while(inwardPixel!=null){
						
						// Grab the next one:
						ScannerPixel outwardPixel=inwardPixel.Next;
						
						
						if(outwardPixel==null){
							break;
						}
						
						// Index of the last pixel (exclusive):
						int max=outwardPixel.PixelIndex;
						
						if(max>lineMax){
							// Clip it:
							max=lineMax;
						}
						
						// The section from inwardPixel to outwardPixel is filled.
						
						if(fillAlpha){
							
							for(int p=inwardPixel.PixelIndex;p<max;p++){
								
								// Get the index:
								int index=pixelIndex+p;
								
								// Grab the colour:
								Color32 colour=atlasPixels[index];
								
								// Alpha blend:
								int dstA=(colour.a * alphaInvert) / 255;
								int cA=fill.a + dstA;
								
								colour.a=(byte)cA;
								colour.r=(byte) ((fillRA + colour.r * dstA)/cA);
								colour.g=(byte) ((fillGA + colour.g * dstA)/cA);
								colour.b=(byte) ((fillBA + colour.b * dstA)/cA);
								
								// Fill:
								atlasPixels[index]=colour;
								
							}
							
						}else{
						
							for(int p=inwardPixel.PixelIndex;p<max;p++){
								
								// Fill:
								atlasPixels[pixelIndex+p]=fill;
								
							}
							
						}
						
						if(outwardPixel==null){
							
							// No more pairs:
							break;
							
						}
						
						// Go to the next intersect:
						inwardPixel=outwardPixel.Next;
						
					}
					
					// Advance to the next line:
					pixelIndex+=atlasWidth;
					
				}
				
				
			}
			
			return true;
			
			/*
			// Create the output.
			SubScanPixel[][] intersects=new SubScanPixel[height][];
			
			for(int i=0;i<height;i++){
				
				// Flatten the scan line into the pixel buffer:
				intersects[i]=ScanLineBuffer[i].Flatten();
				
			}
			
			// Finally create the raster:
			RasterGlyph raster=new RasterGlyph();
			
			// Apply intersects:
			raster.Intersects=intersects;
			
			// Apply width:
			raster.Width=width;
			
			return raster;
			*/
			
		}
Пример #37
0
 public CurveSampler(VectorPath path)
 {
     Path = path;
 }
Пример #38
0
//--------------------------------------