Базовый класс заливки.
Example #1
0
        private void renderMultipleThreads(IScannable obj, FillBase fill)
        {
            _objectPool.Add(obj);
            _fillPool.Add(fill);

            if (!_unlimitedPool && _objectPool.Count == _poolSize)
            {
                Flush();
            }
        }
Example #2
0
        /// <summary>
        /// Выводит объект.
        /// </summary>
        /// <param name="obj">Объект</param>
        /// <param name="fill">Заливка</param>
        public void Render(IScannable obj, FillBase fill)
        {
            switch (_parallelizationLevel)
            {
            case ParallelizationLevel.Single:
                renderSingleThread(obj, fill);
                break;

            case ParallelizationLevel.Duo:
            case ParallelizationLevel.Quad:
                renderMultipleThreads(obj, fill);
                break;
            }
        }
Example #3
0
        private void renderSingleThread(IScannable obj, FillBase fill)
        {
            IList <PixelSpan> spans = null;

            if (obj.BoundingBox.Width >= obj.BoundingBox.Height)
            {
                spans = _spanGenerator.GetHorizontalSpans(obj, 0, 0, _rasterData.Width, _rasterData.Height, fill);
            }
            else
            {
                spans = _spanGenerator.GetVerticalSpans(obj, 0, 0, _rasterData.Width, _rasterData.Height, fill);
            }

            foreach (PixelSpan ps in spans)
            {
                _rasterData.BlendSpan(ps);
            }
        }
Example #4
0
        private void addSpans(Orientation orientation, List<PixelSpan> spans, List<float[]> pixelScanIntersections, int scanPosition, FillBase fill)
        {
            if (pixelScanIntersections.Count == 0)
                return;

            float min = float.MaxValue;
            float max = float.MinValue;

            foreach (float[] subPixelSpan in pixelScanIntersections)
                for (int i = 0; i < subPixelSpan.Length; i++)
                {
                    float spsi = subPixelSpan[i];
                    if (spsi < min)
                        min = spsi;
                    if (spsi > max)
                        max = spsi;
                }

            if (max <= min) return;

            float[] pixelCoverage = new float[(int)(max + 2) - (int)min];

            int shift = (int)min;

            // вычисление покрытия пикселей
            foreach (float[] subPixelSpan in pixelScanIntersections)
            {
                int subPixelSpanLength = subPixelSpan.Length; 
                if (subPixelSpanLength > 0)
                {
                    for (int k = 0; k < subPixelSpanLength; k += 2)
                    {
                        float spanStart = subPixelSpan[k];
                        float spanEnd = subPixelSpan[k + 1];

                        // длина пересечения сканирующего отрезка с объектом меньше единицы
                        // и это пересечение не пересекает границы пикселей
                        if ((int)spanEnd == (int)spanStart ||
                            (int)spanEnd == (int)spanStart + 1)
                            if (spanEnd - spanStart < 1)
                            {
                                pixelCoverage[(int)spanStart - shift] += spanEnd - spanStart;
                                continue;
                            }

                        // пиксели, пересеченные сканирующим отрезком "насквозь"
                        float hv = spanEnd - shift - 1;
                        for (int pixelIndex = (int)spanStart + 1 - shift; pixelIndex < hv; pixelIndex++)
                            pixelCoverage[pixelIndex]++;

                        // пиксель, в котором начался сканирующий отрезок
                        pixelCoverage[(int)spanStart - shift] += 1 - (spanStart - (int)spanStart);

                        // пиксель, в котором закончился сканирующий отрезок
                        if (hv == (int)hv)
                            pixelCoverage[(int)hv] += 1;
                        else
                            pixelCoverage[(int)hv + 1] += spanEnd - (int)spanEnd;
                    }
                }
            }

            // вычисление горизонтальных последовательностей символов
            int spanStartIndex = 0;
            bool spanStarted = false;
            int coverageArrayHiIndex = pixelCoverage.Length - 1;
            float alphaStep = 255f / _subPixelLevel;
            for (int i = 0; i <= coverageArrayHiIndex; i++)
            {
                if (!spanStarted)
                {
                    if (pixelCoverage[i] > 0)
                    {
                        spanStartIndex = i;
                        spanStarted = true;
                    }
                }
                else
                {
                    if (pixelCoverage[i] == 0 || i == coverageArrayHiIndex)
                    {
                        Int32[] pixelValues = new int[i - spanStartIndex];
                        int f = 0;
                        switch(orientation)
                        {
                            case Orientation.Horizontal:
                                for (int k = spanStartIndex; k < i; k++)
                                {
                                    double coverage = pixelCoverage[k];
                                    if (coverage > _subPixelLevel)
                                        coverage = _subPixelLevel;

                                    double antiAliasingAlpha = _alphaTable[(int)(coverage / _subPixelLevel * 254f)];

                                    Int32 color = fill.GetPixelColor((int)min + f + spanStartIndex, scanPosition);
                                    byte fillAlpha = (byte)(color >> 24 & 0xFF);
                                    if (fillAlpha == 0)
                                        pixelValues[f] = (byte)(antiAliasingAlpha * 255f) << 24 | color;
                                    else
                                        pixelValues[f] = (byte)(antiAliasingAlpha * fillAlpha) << 24 | (color & 0x00FFFFFF);

                                    f++;
                                }
                                spans.Add(new PixelSpan(Orientation.Horizontal, (int)min + spanStartIndex, scanPosition, pixelValues));
                                break;

                            case Orientation.Vertical:
                                for (int k = spanStartIndex; k < i; k++)
                                {
                                    double coverage = pixelCoverage[k];
                                    if (coverage > _subPixelLevel)
                                        coverage = _subPixelLevel;

                                    double antiAliasingAlpha = _alphaTable[(int)(coverage / _subPixelLevel * 254f)];

                                    Int32 color = fill.GetPixelColor(scanPosition, (int)min + f + spanStartIndex);
                                    byte fillAlpha = (byte)(color >> 24 & 0xFF);
                                    if (fillAlpha == 0)
                                        pixelValues[f] = (byte)(antiAliasingAlpha * 255f) << 24 | color;
                                    else
                                        pixelValues[f] = (byte)(antiAliasingAlpha * fillAlpha) << 24 | (color & 0x00FFFFFF);

                                    f++;
                                }
                                spans.Add(new PixelSpan(Orientation.Vertical, scanPosition, (int)min + spanStartIndex, pixelValues));
                                break;
                        }
                        spanStarted = false;
                    }
                }
            }
        }
Example #5
0
        /// <summary>
        /// Возвращает вертикальные последовательности пикселей для
        /// геометрической фигуры.
        /// </summary>
        /// <param name="sourceGeometry"></param>
        /// <param name="fill">Заливка</param>
        /// <param name="minX"></param>
        /// <param name="minY"></param>
        /// <param name="maxX"></param>
        /// <param name="maxY"></param>
        /// <returns>Список вертикальных последовательностей символов</returns>
        public IList<PixelSpan> GetVerticalSpans(IScannable sourceGeometry, int minX, int minY, int maxX, int maxY, FillBase fill)
        {
            List<PixelSpan> spans = new List<PixelSpan>();

            BoundingRectangle br = sourceGeometry.BoundingBox;

            float startY = Math.Max((float)br.MinY, minY);
            float endY = Math.Min((float)br.MaxY + 1, maxY);
            float startX = (int)Math.Max((float)br.MinX - 1, minX);
            float endX = Math.Min((float)br.MaxX + 1, maxX);

            sourceGeometry.InitScaning((int)startX, (int)endX, minY, maxY, Orientation.Vertical);

            List<float[]> pixelScanIntersections = new List<float[]>();
            for (float scanX = startX; scanX < endX; scanX++)
            {
                pixelScanIntersections.Clear();
                for (byte i = 0; i < _subPixelLevel; i++)
                {
                    float[] intersections;
                    sourceGeometry.ComputeVerticalIntersections(scanX + _scanStep * i, out intersections);
                    pixelScanIntersections.Add(intersections);
                }
                addSpans(Orientation.Vertical, spans, pixelScanIntersections, (int)scanX, fill);
            }

            return spans;
        }
Example #6
0
        private void addSpans(Orientation orientation, List <PixelSpan> spans, List <float[]> pixelScanIntersections, int scanPosition, FillBase fill)
        {
            if (pixelScanIntersections.Count == 0)
            {
                return;
            }

            float min = float.MaxValue;
            float max = float.MinValue;

            foreach (float[] subPixelSpan in pixelScanIntersections)
            {
                for (int i = 0; i < subPixelSpan.Length; i++)
                {
                    float spsi = subPixelSpan[i];
                    if (spsi < min)
                    {
                        min = spsi;
                    }
                    if (spsi > max)
                    {
                        max = spsi;
                    }
                }
            }

            if (max <= min)
            {
                return;
            }

            float[] pixelCoverage = new float[(int)(max + 2) - (int)min];

            int shift = (int)min;

            // вычисление покрытия пикселей
            foreach (float[] subPixelSpan in pixelScanIntersections)
            {
                int subPixelSpanLength = subPixelSpan.Length;
                if (subPixelSpanLength > 0)
                {
                    for (int k = 0; k < subPixelSpanLength; k += 2)
                    {
                        float spanStart = subPixelSpan[k];
                        float spanEnd   = subPixelSpan[k + 1];

                        // длина пересечения сканирующего отрезка с объектом меньше единицы
                        // и это пересечение не пересекает границы пикселей
                        if ((int)spanEnd == (int)spanStart ||
                            (int)spanEnd == (int)spanStart + 1)
                        {
                            if (spanEnd - spanStart < 1)
                            {
                                pixelCoverage[(int)spanStart - shift] += spanEnd - spanStart;
                                continue;
                            }
                        }

                        // пиксели, пересеченные сканирующим отрезком "насквозь"
                        float hv = spanEnd - shift - 1;
                        for (int pixelIndex = (int)spanStart + 1 - shift; pixelIndex < hv; pixelIndex++)
                        {
                            pixelCoverage[pixelIndex]++;
                        }

                        // пиксель, в котором начался сканирующий отрезок
                        pixelCoverage[(int)spanStart - shift] += 1 - (spanStart - (int)spanStart);

                        // пиксель, в котором закончился сканирующий отрезок
                        if (hv == (int)hv)
                        {
                            pixelCoverage[(int)hv] += 1;
                        }
                        else
                        {
                            pixelCoverage[(int)hv + 1] += spanEnd - (int)spanEnd;
                        }
                    }
                }
            }

            // вычисление горизонтальных последовательностей символов
            int   spanStartIndex       = 0;
            bool  spanStarted          = false;
            int   coverageArrayHiIndex = pixelCoverage.Length - 1;
            float alphaStep            = 255f / _subPixelLevel;

            for (int i = 0; i <= coverageArrayHiIndex; i++)
            {
                if (!spanStarted)
                {
                    if (pixelCoverage[i] > 0)
                    {
                        spanStartIndex = i;
                        spanStarted    = true;
                    }
                }
                else
                {
                    if (pixelCoverage[i] == 0 || i == coverageArrayHiIndex)
                    {
                        Int32[] pixelValues = new int[i - spanStartIndex];
                        int     f           = 0;
                        switch (orientation)
                        {
                        case Orientation.Horizontal:
                            for (int k = spanStartIndex; k < i; k++)
                            {
                                double coverage = pixelCoverage[k];
                                if (coverage > _subPixelLevel)
                                {
                                    coverage = _subPixelLevel;
                                }

                                double antiAliasingAlpha = _alphaTable[(int)(coverage / _subPixelLevel * 254f)];

                                Int32 color     = fill.GetPixelColor((int)min + f + spanStartIndex, scanPosition);
                                byte  fillAlpha = (byte)(color >> 24 & 0xFF);
                                if (fillAlpha == 0)
                                {
                                    pixelValues[f] = (byte)(antiAliasingAlpha * 255f) << 24 | color;
                                }
                                else
                                {
                                    pixelValues[f] = (byte)(antiAliasingAlpha * fillAlpha) << 24 | (color & 0x00FFFFFF);
                                }

                                f++;
                            }
                            spans.Add(new PixelSpan(Orientation.Horizontal, (int)min + spanStartIndex, scanPosition, pixelValues));
                            break;

                        case Orientation.Vertical:
                            for (int k = spanStartIndex; k < i; k++)
                            {
                                double coverage = pixelCoverage[k];
                                if (coverage > _subPixelLevel)
                                {
                                    coverage = _subPixelLevel;
                                }

                                double antiAliasingAlpha = _alphaTable[(int)(coverage / _subPixelLevel * 254f)];

                                Int32 color     = fill.GetPixelColor(scanPosition, (int)min + f + spanStartIndex);
                                byte  fillAlpha = (byte)(color >> 24 & 0xFF);
                                if (fillAlpha == 0)
                                {
                                    pixelValues[f] = (byte)(antiAliasingAlpha * 255f) << 24 | color;
                                }
                                else
                                {
                                    pixelValues[f] = (byte)(antiAliasingAlpha * fillAlpha) << 24 | (color & 0x00FFFFFF);
                                }

                                f++;
                            }
                            spans.Add(new PixelSpan(Orientation.Vertical, scanPosition, (int)min + spanStartIndex, pixelValues));
                            break;
                        }
                        spanStarted = false;
                    }
                }
            }
        }
Example #7
0
        /// <summary>
        /// Возвращает вертикальные последовательности пикселей для
        /// геометрической фигуры.
        /// </summary>
        /// <param name="sourceGeometry"></param>
        /// <param name="fill">Заливка</param>
        /// <param name="minX"></param>
        /// <param name="minY"></param>
        /// <param name="maxX"></param>
        /// <param name="maxY"></param>
        /// <returns>Список вертикальных последовательностей символов</returns>
        public IList <PixelSpan> GetVerticalSpans(IScannable sourceGeometry, int minX, int minY, int maxX, int maxY, FillBase fill)
        {
            List <PixelSpan> spans = new List <PixelSpan>();

            BoundingRectangle br = sourceGeometry.BoundingBox;

            float startY = Math.Max((float)br.MinY, minY);
            float endY   = Math.Min((float)br.MaxY + 1, maxY);
            float startX = (int)Math.Max((float)br.MinX - 1, minX);
            float endX   = Math.Min((float)br.MaxX + 1, maxX);

            sourceGeometry.InitScaning((int)startX, (int)endX, minY, maxY, Orientation.Vertical);

            List <float[]> pixelScanIntersections = new List <float[]>();

            for (float scanX = startX; scanX < endX; scanX++)
            {
                pixelScanIntersections.Clear();
                for (byte i = 0; i < _subPixelLevel; i++)
                {
                    float[] intersections;
                    sourceGeometry.ComputeVerticalIntersections(scanX + _scanStep * i, out intersections);
                    pixelScanIntersections.Add(intersections);
                }
                addSpans(Orientation.Vertical, spans, pixelScanIntersections, (int)scanX, fill);
            }

            return(spans);
        }
Example #8
0
 /// <summary>
 /// Выводит объект.
 /// </summary>
 /// <param name="obj">Объект</param>
 /// <param name="fill">Заливка</param>
 public void Render(IScannable obj, FillBase fill)
 {
     switch(_parallelizationLevel)
     {
         case ParallelizationLevel.Single:
             renderSingleThread(obj, fill);
             break;
         case ParallelizationLevel.Duo:
         case ParallelizationLevel.Quad:
             renderMultipleThreads(obj, fill);
             break;
     }
 }
Example #9
0
        private void renderMultipleThreads(IScannable obj, FillBase fill)
        {
            _objectPool.Add(obj);
            _fillPool.Add(fill);

            if (!_unlimitedPool && _objectPool.Count == _poolSize)
                Flush();
        }
Example #10
0
        private void renderSingleThread(IScannable obj, FillBase fill)
        {
            IList<PixelSpan> spans = null;
            if (obj.BoundingBox.Width >= obj.BoundingBox.Height)
                spans = _spanGenerator.GetHorizontalSpans(obj, 0, 0, _rasterData.Width, _rasterData.Height, fill);
            else
                spans = _spanGenerator.GetVerticalSpans(obj, 0, 0, _rasterData.Width, _rasterData.Height, fill);

            foreach (PixelSpan ps in spans)
                _rasterData.BlendSpan(ps);
        }