Пример #1
0
        public void CreateDistanceCache()
        {
            // Create the caches:
            DistanceCache = new DistanceCacheSquare[DistanceCacheWidth * DistanceCacheHeight];

            // The cell square index:
            int index = 0;

            // For each cell..
            for (int y = 0; y < DistanceCacheHeight; y++)
            {
                for (int x = 0; x < DistanceCacheWidth; x++)
                {
                    // Create it:
                    DistanceCache[index] = new DistanceCacheSquare(x, y, index);

                    index++;
                }
            }

            index = 0;

            // For each cell..
            for (int y = 0; y < DistanceCacheHeight; y++)
            {
                for (int x = 0; x < DistanceCacheWidth; x++)
                {
                    // Set it up (done like this as it accesses other squares in cache):
                    DistanceCache[index].Setup(this);

                    index++;
                }
            }
        }
Пример #2
0
		public void CreateDistanceCache(){
			
			// Create the caches:
			DistanceCache=new DistanceCacheSquare[DistanceCacheWidth * DistanceCacheHeight];
			
			// The cell square index:
			int index=0;
			
			// For each cell..
			for(int y=0;y<DistanceCacheHeight;y++){
				
				for(int x=0;x<DistanceCacheWidth;x++){
					
					// Create it:
					DistanceCache[index]=new DistanceCacheSquare(x,y,index);
					
					index++;
					
				}
				
			}
			
			index=0;
			
			// For each cell..
			for(int y=0;y<DistanceCacheHeight;y++){
				
				for(int x=0;x<DistanceCacheWidth;x++){
					
					// Set it up (done like this as it accesses other squares in cache):
					DistanceCache[index].Setup(this);
					
					index++;
					
				}
				
			}
			
		}
Пример #3
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;
             */
        }