public DreamEffect()
        {
            Name = "Dream";

            var diagonalGradient = new LinearGradient
            {
                StartPoint = new Point(0.0, 0.0),
                EndPoint = new Point(1.0, 1.0),

                Stops = new[]
                {
                    new GradientStop {Offset = 0, Color = Color.FromArgb(255, 133, 147, 201)},
                    new GradientStop {Offset = 1.0, Color = Color.FromArgb(255, 245, 152, 157)}
                }
            };

            var overlayFactory = new OverlayFactory(
                "ms-appx:///images/Filters_Landscape_Overlay_Dream.jpg", 
                "ms-appx:///images/Filters_Portrait_Overlay_Dream.jpg", 
                "ms-appx:///images/Filters_Square_Overlay_Dream.jpg");

            LayerList = new LayerList(
				new AdjustmentLayer(LayerStyle.Normal(), new LevelsEffect(0.75, 0.85, 0.15)),
                new Layer(LayerStyle.Softlight(), context => new GradientImageSource(context.BackgroundLayer.ImageSize, diagonalGradient)),
                new Layer(LayerStyle.Overlay(), context => overlayFactory.CreateAsync(context.BackgroundLayer.ImageSize))
            );
        }
        public LinearGradientImageSourceEffectProcessor()
        {
            Name = "Linear Gradient";

            m_endX = 1.0;
            m_endY = 1.0;

            m_linearGradient = new LinearGradient(new Point(0.0, 0.0), new Point(1.0, 1.0));
            m_linearGradient.Stops = new[]
                         {
                             new GradientStop{Offset=0.0, Color=Colors.Red},
                             new GradientStop{Offset=0.5, Color=Colors.Green},
                             new GradientStop{Offset=1.0, Color=Colors.Cyan}
                         };

            m_gradientImageSource = new GradientImageSource(new Size(800,500), m_linearGradient);

            SetupEffectCategory(m_gradientImageSource);

            m_propertyDescriptions = new Dictionary<string, PropertyDescription>();
            m_propertyDescriptions.Add("StartX", new PropertyDescription(-1.0, 2.0, 0));
            m_propertyDescriptions.Add("StartY", new PropertyDescription(-1.0, 2.0, 0));
            m_propertyDescriptions.Add("EndX", new PropertyDescription(-1.0, 2.0, 0));
            m_propertyDescriptions.Add("EndY", new PropertyDescription(-1.0, 2.0, 0));

            AddEditors();   

             
        }
		private static void SetGradientStops(LinearGradient gradient, FocusBand focusBand, Size sourceSize, KernelGenerator edge1KernelGenerator, KernelGenerator edge2KernelGenerator, bool applySmallBlurFocusArea)
		{
			var blurArea1FirstOffset = GetOffset(gradient, focusBand.Edge1);
			var blurArea2FirstOffset = GetOffset(gradient, focusBand.Edge2);

			var focusBandEdge1Pixels = new Point(focusBand.Edge1.X * sourceSize.Width, focusBand.Edge1.Y * sourceSize.Height);
			var focusBandEdge2Pixels = new Point(focusBand.Edge2.X * sourceSize.Width, focusBand.Edge2.Y * sourceSize.Height);

			var focusBandWidth = Math.Abs(blurArea1FirstOffset - blurArea2FirstOffset);
            var focusBandWidthPixels = Distance(focusBandEdge1Pixels, focusBandEdge2Pixels);

            double blurAreaWidth;
            if (focusBandWidthPixels > 0)
            {
                var scaleFactor = focusBandWidth / focusBandWidthPixels;

                var blurAreaWidthPixels = (sourceSize.Height - focusBandWidthPixels) / 2 * 0.9;

                if (blurAreaWidthPixels < 1.0)
                {
                    gradient.Stops = new[] { new GradientStop() { Offset = 0.5, Color = Color.FromArgb(255, 0, 0, 0) } };
                    return;
                }

                blurAreaWidth = blurAreaWidthPixels * scaleFactor;
            }
            else
            {
                blurAreaWidth = 0.5;
                applySmallBlurFocusArea = true;
            }

			double blurArea1LastOffset;
			double blurArea2LastOffset;

			if (blurArea1FirstOffset > blurArea2FirstOffset)
			{
				blurArea1LastOffset = blurArea1FirstOffset + blurAreaWidth;
				blurArea2LastOffset = blurArea2FirstOffset - blurAreaWidth;
			}
			else
			{
				blurArea1LastOffset = blurArea1FirstOffset - blurAreaWidth;
				blurArea2LastOffset = blurArea2FirstOffset + blurAreaWidth;
			}

			var stops1 = GetGradientStops(gradient, applySmallBlurFocusArea, edge1KernelGenerator, blurArea1FirstOffset, blurArea1LastOffset);
			var stops2 = GetGradientStops(gradient, applySmallBlurFocusArea, edge2KernelGenerator, blurArea2FirstOffset, blurArea2LastOffset, (byte)(edge1KernelGenerator.GetKernelBands().Count));

			List<GradientStop> stops = new List<GradientStop>();
			stops.AddRange(stops1);
			stops.AddRange(stops2);

			var validStops = EnsureMinDiffBetweenPoints(stops);

			gradient.Stops = validStops.ToArray();
		}
		/// <summary>
		/// Provides a configured LinearGradient that can be used in combination with a GradientImageSource to provide a mask for the LensBlurEffect.
		/// Generates a map for BlendEffect.
		/// </summary>
		/// <param name="band">The band that represents the focus area in the image. Pixels within this band won't be blurred. 
		/// Areas outside of the area will be progressively more blurred as the distance from the focus band increases.</param>
		/// <param name="kernelSpanFromEdge1">Strength at Edge1.</param>
		/// <param name="kernelSpanFromEdge2">Strength at Edge2.</param>
		/// <returns>A LinearGradient that can be used in combination with a GradientImageSource to be used by LensBlur.</returns>

		public static LinearGradient GenerateGradient(FocusBand band, Size sourceSize, KernelGenerator edge1KernelGenerator, KernelGenerator edge2KernelGenerator, bool applySmallBlurFocusArea)
		{
			var gradient = new LinearGradient();

			var lineFunction = GradientLine.CreateFunction(band);

			SetGradientPoints(gradient, lineFunction);
            SetGradientStops(gradient, band, sourceSize, edge1KernelGenerator, edge2KernelGenerator, applySmallBlurFocusArea);

			return gradient;
		}
示例#5
0
        public static ColorBase GetColor(Brush brush, double opacity, Rect bounds, double angle = 0)
        {
            var solidBrush = brush as SolidColorBrush;
            if (solidBrush != null)
            {
                return GetRgbColor(solidBrush.Color, opacity);
            }

            var linerBrush = brush as LinearGradientBrush;
            if (linerBrush != null)
            {
                var startPoint = new Point(bounds.X + linerBrush.StartPoint.X * bounds.Width, bounds.Y + linerBrush.StartPoint.Y * bounds.Height);
                var endPoint = new Point(bounds.X + linerBrush.EndPoint.X * bounds.Width, bounds.Y + linerBrush.EndPoint.Y * bounds.Height);
                LinearGradient gradient = new LinearGradient(startPoint, endPoint);
                foreach (var stop in linerBrush.GradientStops)
                {
                    gradient.GradientStops.Add(new Telerik.Windows.Documents.Fixed.Model.ColorSpaces.GradientStop(GetRgbColor(stop.Color, opacity), stop.Offset));
                }

                gradient.Position.RotateAt(angle, bounds.Center().X, bounds.Center().Y);

                return gradient;
            }

            var radialBrush = brush as RadialGradientBrush;
            if (radialBrush != null)
            {
                var startPoint = new Point(bounds.X + radialBrush.GradientOrigin.X * bounds.Width, bounds.Y + radialBrush.GradientOrigin.Y * bounds.Height);
                var endPoint = new Point(bounds.X + radialBrush.Center.X * bounds.Width, bounds.Y + radialBrush.Center.Y * bounds.Height);
                var radiusX = radialBrush.RadiusX * bounds.Width;
                var radiusY = radialBrush.RadiusY * bounds.Height;
                Point scale = new Point(1, 1);
                if (radiusX > radiusY)
                    scale.X = radiusX / radiusY;
                else if (radiusY > radiusX)
                    scale.Y = radiusY / radiusX;
                RadialGradient gradient = new RadialGradient(startPoint, endPoint, 0, Math.Min(radiusX, radiusY));

                for (int i = 0; i < radialBrush.GradientStops.Count; i++)
                {
                    var stop = radialBrush.GradientStops[i];
                    var color = GetRgbColor(stop.Color, opacity);
                    gradient.GradientStops.Add(new Telerik.Windows.Documents.Fixed.Model.ColorSpaces.GradientStop(color, stop.Offset));
                }

                gradient.Position.ScaleAt(scale.X, scale.Y, bounds.Center().X, bounds.Center().Y);
                gradient.Position.RotateAt(angle, bounds.Center().X, bounds.Center().Y);

                return gradient;
            }

            return RgbColors.Black;
        }
示例#6
0
        void DrawBookmark(Context cr, double x, double y)
        {
            var color1 = Style.BookmarkColor1;
            var color2 = Style.BookmarkColor2;

            DrawRoundRectangle(cr, x + 1, y + 1, 8, Width - 4, Editor.LineHeight - 4);
            using (var pat = new LinearGradient(x + Width / 4, y, x + Width / 2, y + Editor.LineHeight - 4)) {
                pat.AddColorStop(0, color1);
                pat.AddColorStop(1, color2);
                cr.Pattern = pat;
                cr.FillPreserve();
            }

            using (var pat = new LinearGradient(x, y + Editor.LineHeight, x + Width, y)) {
                pat.AddColorStop(0, color2);
                //pat.AddColorStop (1, color1);
                cr.Pattern = pat;
                cr.Stroke();
            }
        }
        public RetroEffect()
        {
            var globalCurve = new Curve
            {
                Points = new[]
                {
                    new Point(0, 0),
                    new Point(41, 59),
                    new Point(112, 146),
                    new Point(189, 211),
                    new Point(255, 255)                 
                }
            };

            var redCurve = new Curve(CurveInterpolation.NaturalCubicSpline, new[]
            {
                new Point(0, 0),
                new Point(75, 61),
                new Point(255, 255)
            });

            Curve.Compose(redCurve, globalCurve, redCurve);


            var greenCurve = new Curve(CurveInterpolation.NaturalCubicSpline, new[]
            {
                new Point(0, 0),
                new Point(59, 34),
                new Point(182, 199),
                new Point(255, 255)

            });

            Curve.Compose(greenCurve, globalCurve, greenCurve);

            var blueCurve = new Curve(CurveInterpolation.NaturalCubicSpline, new[]
            {
                new Point(0, 91),
                new Point(128, 128),
                new Point(255, 185)

            });

            Curve.Compose(blueCurve, globalCurve, blueCurve);

            var yellowPurpleGradient = new LinearGradient
            {
                StartPoint = new Point(0.0, 0.5),
                EndPoint = new Point(1.0, 0.5),

                Stops = new[]
                {
                    new GradientStop {Offset = 0, Color = Color.FromArgb(255, 255, 255, 0)},
                    new GradientStop {Offset = 0.5, Color = Color.FromArgb(255, 148, 106, 77)},
                    new GradientStop {Offset = 1.0, Color = Color.FromArgb(255, 72, 3, 131)}
                }
            };

            var redTransparentGradient = new LinearGradient
            {
                StartPoint = new Point(0.0, 0.5),
                EndPoint = new Point(1.0, 0.5),

                Stops = new[]
                {
                    new GradientStop {Offset = 0, Color = Color.FromArgb(255, 255, 0, 0)},
                    new GradientStop {Offset = 1.0, Color = Color.FromArgb(0, 255, 0, 0)}
                }
            };

            var spotGradient = new RadialGradient
            {
                CenterPoint = new Point(0.5, 0.3),
                EllipseRadius = new EllipseRadius(0, 0.2),
                Stops = new[]
                {
                    new GradientStop {Offset = 0.0, Color = Color.FromArgb(255, 255, 255, 255)},
                    new GradientStop {Offset = 1.0, Color = Color.FromArgb(0, 255, 255, 255)}
                }
            };


            var vignetteGradient = new RadialGradient
            {
                CenterPoint = new Point(0.5, 0.5),
                EllipseRadius = new EllipseRadius(1.0, 0),
                Stops = new[]
                {
                    new GradientStop {Offset = 0, Color = Color.FromArgb(255, 255, 255, 255)},
                    new GradientStop {Offset = 0.9, Color = Color.FromArgb(255, 0, 0, 0)}
                }
            };

            LayerList = new LayerList()
            {
                new AdjustmentLayer(LayerStyle.Normal(), new CurvesEffect(redCurve, greenCurve, blueCurve)),
                new Layer(LayerStyle.Softlight(0.3), context => new GradientImageSource(context.BackgroundLayer.ImageSize, yellowPurpleGradient)),
                new Layer(LayerStyle.Screen(0.75, targetArea: new Rect(0, 0, 0.4, 1.0)), context => new GradientImageSource(new Size(context.BackgroundLayer.ImageSize.Width * 0.4, context.BackgroundLayer.ImageSize.Height), redTransparentGradient)),
                new Layer(LayerStyle.Softlight(), context => new GradientImageSource(context.BackgroundLayer.ImageSize, spotGradient)),
                new Layer(LayerStyle.Softlight(0.6), context => new GradientImageSource(context.BackgroundLayer.ImageSize, vignetteGradient))
            };
        }
		private static void SetGradientPoints(LinearGradient gradient, Func<double, Point> pointFunction)
		{
			gradient.StartPoint = pointFunction(0);
			gradient.EndPoint = pointFunction(1);
		}
		private static double GetOffset(LinearGradient gradient, Point p)
		{

			var distnacePFromP1 = Distance(p, gradient.StartPoint);
			var distnaceP1FromP2 = Distance(gradient.StartPoint, gradient.EndPoint);

			var offset = distnacePFromP1 / distnaceP1FromP2;
			return offset;
		}
        private static Tiling CreateTiling(double offsetX, double offsetY, double width, SimpleColor color)
        {
            Tiling tiling = new Tiling(new Rect(0, 0, width, 2));
            tiling.Position.Translate(offsetX, offsetY);
            var tilingEditor = new FixedContentEditor(tiling);
            tilingEditor.GraphicProperties.IsStroked = false;
            tilingEditor.GraphicProperties.FillColor = color;
            tilingEditor.DrawRectangle(new Rect(0, 0, width, 1));
            LinearGradient gradient = new LinearGradient(new Point(0, 0), new Point(width, 0));
            gradient.GradientStops.Add(new GradientStop(color, 0));
            gradient.GradientStops.Add(new GradientStop(RgbColors.White, .5));
            gradient.GradientStops.Add(new GradientStop(color, 1));
            tilingEditor.GraphicProperties.FillColor = gradient;
            tilingEditor.DrawRectangle(new Rect(0, 1, width, 1));

            return tiling;
        }
		public GlamMeLomoEffect()
        {
            var globalCurve = new Curve(CurveInterpolation.NaturalCubicSpline, new[]
            {                  
                    new Point(0, 0),
                    new Point(41, 59),
                    new Point(112, 146),
                    new Point(189, 211),
                    new Point(255, 255)
            });

            var redCurve = new Curve(CurveInterpolation.NaturalCubicSpline, new[]
            {
                new Point(0, 0),
                new Point(101, 45),
                new Point(191, 193),
                new Point(255, 255)
            });
            
            Curve.Compose(redCurve, globalCurve, redCurve);

            var greenCurve = new Curve(CurveInterpolation.NaturalCubicSpline, new[]
            {
                new Point(0, 0),
                new Point(78, 61),
                new Point(187, 199),
                new Point(255, 255)
            });

            Curve.Compose(greenCurve, globalCurve, greenCurve);

            var blueCurve = new Curve(CurveInterpolation.NaturalCubicSpline, new[]
            {
                new Point(0, 0),
                new Point(56, 71),
                new Point(204, 181),
                new Point(255, 255)
            });
            
            Curve.Compose(blueCurve, globalCurve, blueCurve);

            var linearGradient = new LinearGradient
            {
                StartPoint = new Point(0.0, 0.5),
                EndPoint = new Point(1.0, 0.5),

                Stops = new[]
                {
                    new GradientStop {Offset = 0, Color = Color.FromArgb(255, 135, 135, 135) },
                    new GradientStop {Offset = 1.0, Color = Color.FromArgb(255, 193, 193, 193) }
                }
            };

            var vignetteGradient = new RadialGradient
            {
                CenterPoint = new Point(0.5, 0.5),
                EllipseRadius = new EllipseRadius(2.0, 0),
                Stops = new[]
                {
                    new GradientStop {Offset = 0, Color = Color.FromArgb(0, 255, 255, 255)},
                    new GradientStop {Offset = 0.9, Color = Color.FromArgb(255, 0, 0, 0)}
                }
            };

            var vignette2Gradient = new RadialGradient
            {
                CenterPoint = new Point(0.5, 0.5),
                EllipseRadius = new EllipseRadius(1.0, 0),
                Stops = new[]
                {
                    new GradientStop {Offset = 0, Color = Color.FromArgb(0, 0, 0, 0)},                  
                    new GradientStop {Offset = 0.5, Color = Color.FromArgb(0, 0, 0, 0)},                  
                    new GradientStop {Offset = 1.0, Color = Color.FromArgb(255, 0, 0, 0)}
                }
            };

            LayerList = new LayerList()
            {
                new AdjustmentLayer(LayerStyle.Normal(), new CurvesEffect(redCurve, greenCurve, blueCurve)),
                new Layer(LayerStyle.Overlay(), context => new GradientImageSource(context.BackgroundLayer.ImageSize, linearGradient)),
                new Layer(LayerStyle.Softlight(0.4), context => new GradientImageSource(context.BackgroundLayer.ImageSize, vignetteGradient)),
                new Layer(LayerStyle.Darken(0.5), context => new GradientImageSource(context.BackgroundLayer.ImageSize, vignette2Gradient))
            };
        }
 /// <summary>
 /// Fill to buffer base rows data information using non-zero rule
 /// </summary>
 /// <param name="paint">linear gradient object</param>
 /// <param name="rows">row data information</param>
 /// <param name="startRowIndex">start row index in row array need to draw</param>
 /// <param name="endRowIndex">end row index in end row array need to draw</param>
 /// <param name="isForward">is diagonal gradient is forward</param>
 /// <param name="gammaLutRed">gamma look up table for red</param>
 /// <param name="gammaLutGreen">gamma look up table for green</param>
 /// <param name="gammaLutBlue">gamma look up table for blue</param>
 void OnFillingTransformedDiagonalNonZero(LinearGradient paint, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex, bool isForward, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Fill to buffer base rows data information using non-zero rule
        /// </summary>
        /// <param name="paint">linear gradient object</param>
        /// <param name="rows">row data information</param>
        /// <param name="startRowIndex">start row index in row array need to draw</param>
        /// <param name="endRowIndex">end row index in end row array need to draw</param>
        /// <param name="gammaLutRed">gamma look up table for red</param>
        /// <param name="gammaLutGreen">gamma look up table for green</param>
        /// <param name="gammaLutBlue">gamma look up table for blue</param>
        void OnFillingTransformedVerticalNonZero(LinearGradient paint, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue)
        {
            // now not need to check null or not
            uint[] builtColors = paint.GetLinearColors(opacity);

            #region private variable for filling
            int currentCoverage, scLastCoverage, scLastX = 0;
            int tempCover = 0;
            int currentArea = 0;
            int lastXPosition = 0;
            int startXPosition = 0;
            byte calculatedCoverage = 0;
            int currentColorIndexScaled = 0;
            CellData currentCellData = null;
            uint colorData = 0;
            uint dst, dstRB, dstG;

            //uint colorG = 0;
            //uint colorRB = 0;

            // each row color index will increase value
            double startRowIncrement = 0;
            #endregion

            #region varialbe for vertical
            double startY = paint.StartY;
            double endY = paint.EndY;
            double distance = endY - startY;
            #endregion

            #region variable for transform
            #region transform line 1,1 => 101,1
            double currentYTransformed = 1 * InvertedMatrixShy + 1 * InvertedMatrixSy + InvertedMatrixTy;
            double destYToTransformed = 101 * InvertedMatrixShy + 1 * InvertedMatrixSy + InvertedMatrixTy;
            #endregion
            // in vertical we need increment by x after steps
            double transformedRatio = (destYToTransformed - currentYTransformed) / 100;
            // when transformed horizonline increase 1, x will increase by increment.
            int incrementTranformedColorIndexScaled =
                (int)((transformedRatio / distance) * ColorIndexIncludeIncrementScale);
            #endregion

            #region prepare value for rows
            //transform first cell of row
            currentYTransformed =
                startRowIndex * InvertedMatrixSy + InvertedMatrixTy;
            currentYTransformed = ((currentYTransformed - startY) / distance);

            //calculate row increment
            startRowIncrement = ((InvertedMatrixSy / distance));
            #endregion

            #region FILLING
            if (paint.Ramp.NoBlendingColor)
            {// no blending color
                if (paint.Style != GradientStyle.Pad)
                {
                    #region optimized for reflect and repeat mode
                    incrementTranformedColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                    if (incrementTranformedColorIndexScaled < 0)
                    {
                        incrementTranformedColorIndexScaled = ColorIndexIncludeIncrementDoubleScale - incrementTranformedColorIndexScaled;
                    }
                    #endregion
                    // when no need to blending, when draw a horizontal line
                    // do not need check the back color, alway setup
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;

                        if (rows[startRowIndex] != null)
                        {
                            #region transform for row
                            currentColorIndexScaled = (int)
                                (currentYTransformed * ColorIndexIncludeIncrementScale);
                            if (currentColorIndexScaled < 0)
                            {
                                currentColorIndexScaled += ColorIndexIncludeIncrementDoubleScale;
                            }
                            currentYTransformed += startRowIncrement;
                            #endregion

                            // get first cell in current row
                            currentCellData = rows[startRowIndex].First;
                            if (currentCellData != null)
                            {
                                #region fill current row
                                do
                                {
                                    currentArea = currentCellData.Area;
                                    #region blend horizontal line
                                    if ((currentCellData.X > scLastX + 1))
                                    {
                                        if (scLastCoverage != 0)
                                        {
                                            // fast bit absolute
                                            scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);
                                            #region non-zero checking code
                                            if (scLastCoverage > 255) scLastCoverage = 255;
                                            #endregion

                                            #region BLEND HORIZONTAL LINE
                                            // calculate start and end position
                                            startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                            lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                            // get current color index value
                                            if (scLastCoverage >= 254)
                                            {
                                                while (startXPosition < lastXPosition)
                                                {
                                                    //BufferData[startXPosition++] = colorData;
                                                    //BufferData[startXPosition++] = builtColors[(currentColorIndexScaled >> IncrementColorIndexShift) ];
                                                    BufferData[startXPosition++] = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift];
                                                    // incre color index
                                                    currentColorIndexScaled += incrementTranformedColorIndexScaled;
                                                    //currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                                                }
                                            }
                                            else
                                            {
                                                while (startXPosition < lastXPosition)
                                                {

                                                    colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift];
                                                    // incre color index
                                                    currentColorIndexScaled += incrementTranformedColorIndexScaled;

                                                    calculatedCoverage = (byte)((colorData >> 24));
                                                    calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);
                                                    if (calculatedCoverage >= 255)
                                                    {
                                                        BufferData[startXPosition] = colorData;
                                                    }
                                                    else
                                                    {
                                                        //// blend here
                                                        //dst = BufferData[startXPosition];
                                                        //dstRB = dst & 0x00FF00FF;
                                                        //dstG = (dst >> 8) & 0xFF;

                                                        //BufferData[startXPosition] =
                                                        //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                        //    | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                        //    | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                        #region gamma apply
                                                        dst = BufferData[startXPosition];
                                                        dstG = (dst >> 8) & 0xFF;
                                                        dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                                        BufferData[startXPosition] =
                                                            (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                            | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                                            | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                                            | (gammaLutBlue[(dstRB & 0x00FF)]));
                                                        #endregion
                                                    }
                                                    startXPosition++;
                                                    currentColorIndexScaled++;
                                                }
                                            }
                                            #endregion
                                        }
                                        else
                                        {
                                            // incre color index
                                            currentColorIndexScaled += (currentCellData.X - scLastX - 1) * incrementTranformedColorIndexScaled;
                                        }
                                    }
                                    #endregion

                                    currentCoverage += currentCellData.Coverage;

                                    #region blend the current cell
                                    tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                                    if (tempCover != 0)
                                    {
                                        // fast bit absolute
                                        tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                        #region non-zero checking code
                                        if (tempCover > 255) tempCover = 255;
                                        #endregion

                                        colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift];

                                        calculatedCoverage = (byte)(colorData >> 24);

                                        #region blend pixel
                                        tempCover = (int)((tempCover * calculatedCoverage) >> 8);
                                        //if (tempCover > 255) tempCover = 255;
                                        calculatedCoverage = (byte)tempCover;

                                        startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                        #region blend here
                                        //dst = BufferData[startXPosition];
                                        //dstRB = dst & 0x00FF00FF;
                                        //dstG = (dst >> 8) & 0xFF;
                                        //BufferData[startXPosition] =
                                        //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                        //    | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                        //    | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                        #region gamma apply
                                        dst = BufferData[startXPosition];
                                        dstG = (dst >> 8) & 0xFF;
                                        dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                        BufferData[startXPosition] =
                                            (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                            | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                            | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                            | (gammaLutBlue[(dstRB & 0x00FF)]));
                                        #endregion

                                        #endregion
                                        #endregion
                                    }
                                    #endregion

                                    // incre color index
                                    currentColorIndexScaled += incrementTranformedColorIndexScaled;

                                    scLastCoverage = currentCoverage;
                                    scLastX = currentCellData.X;

                                    // move to next cell
                                    currentCellData = currentCellData.Next;
                                } while (currentCellData != null);
                                #endregion
                            }
                        }
                    }
                    #endregion
                }
                else
                {//GradientStyle.Pad mode
                    #region GradientStyle.Pad

                    // when no need to blending, when draw a horizontal line
                    // do not need check the back color, alway setup
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;

                        if (rows[startRowIndex] != null)
                        {
                            #region transform for row
                            currentColorIndexScaled = (int)
                                (currentYTransformed * ColorIndexIncludeIncrementScale);
                            //if (currentColorIndexScaled < 0)
                            //{
                            //    currentColorIndexScaled += ColorIndexIncludeIncrementDoubleScale;
                            //}
                            currentYTransformed += startRowIncrement;
                            #endregion

                            // get first cell in current row
                            currentCellData = rows[startRowIndex].First;
                            if (currentCellData != null)
                            {
                                #region fill current row
                                do
                                {
                                    currentArea = currentCellData.Area;
                                    #region blend horizontal line
                                    if ((currentCellData.X > scLastX + 1))
                                    {
                                        if (scLastCoverage != 0)
                                        {
                                            // fast bit absolute
                                            scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);
                                            #region non-zero checking code
                                            if (scLastCoverage > 255) scLastCoverage = 255;
                                            #endregion

                                            #region BLEND HORIZONTAL LINE
                                            // calculate start and end position
                                            startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                            lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                            // get current color index value
                                            if (scLastCoverage >= 254)
                                            {
                                                while (startXPosition < lastXPosition)
                                                {
                                                    //BufferData[startXPosition++] = colorData;
                                                    //BufferData[startXPosition++] = builtColors[(currentColorIndexScaled >> IncrementColorIndexShift) ];
                                                    BufferData[startXPosition++] = builtColors[
                                                        currentColorIndexScaled < 0 ?
                                                            0 :
                                                            (currentColorIndexScaled > ColorIndexIncludeIncrementScale ?
                                                                255 :
                                                                currentColorIndexScaled >> IncrementColorIndexShift)];
                                                    // incre color index
                                                    currentColorIndexScaled += incrementTranformedColorIndexScaled;
                                                    //currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                                                }
                                            }
                                            else
                                            {
                                                while (startXPosition < lastXPosition)
                                                {
                                                    //colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift];
                                                    colorData = builtColors[
                                                        currentColorIndexScaled < 0 ?
                                                            0 :
                                                        (currentColorIndexScaled > ColorIndexIncludeIncrementScale ?
                                                            255 :
                                                            currentColorIndexScaled >> IncrementColorIndexShift)];
                                                    // incre color index
                                                    currentColorIndexScaled += incrementTranformedColorIndexScaled;

                                                    calculatedCoverage = (byte)((colorData >> 24));
                                                    calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);
                                                    if (calculatedCoverage >= 255)
                                                    {
                                                        BufferData[startXPosition] = colorData;
                                                    }
                                                    else
                                                    {
                                                        // blend here
                                                        //dst = BufferData[startXPosition];
                                                        //dstRB = dst & 0x00FF00FF;
                                                        //dstG = (dst >> 8) & 0xFF;

                                                        //BufferData[startXPosition] =
                                                        //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                        //    | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                        //    | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                        #region gamma apply
                                                        dst = BufferData[startXPosition];
                                                        dstG = (dst >> 8) & 0xFF;
                                                        dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                                        BufferData[startXPosition] =
                                                            (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                            | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                                            | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                                            | (gammaLutBlue[(dstRB & 0x00FF)]));
                                                        #endregion

                                                    }
                                                    startXPosition++;
                                                    currentColorIndexScaled++;
                                                }
                                            }
                                            #endregion
                                        }
                                        else
                                        {
                                            // incre color index
                                            currentColorIndexScaled += (currentCellData.X - scLastX - 1) * incrementTranformedColorIndexScaled;
                                        }
                                    }
                                    #endregion

                                    currentCoverage += currentCellData.Coverage;

                                    #region blend the current cell
                                    tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                                    if (tempCover != 0)
                                    {
                                        // fast bit absolute
                                        tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);
                                        #region non-zero checking code
                                        if (tempCover > 255) tempCover = 255;
                                        #endregion

                                        colorData = builtColors[
                                            currentColorIndexScaled < 0 ?
                                                0 :
                                                (currentColorIndexScaled > ColorIndexIncludeIncrementScale ?
                                                    255 :
                                                    currentColorIndexScaled >> IncrementColorIndexShift)];

                                        calculatedCoverage = (byte)(colorData >> 24);

                                        #region blend pixel
                                        tempCover = (int)((tempCover * calculatedCoverage) >> 8);
                                        //if (tempCover > 255) tempCover = 255;
                                        calculatedCoverage = (byte)tempCover;

                                        startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                        #region blend here
                                        //dst = BufferData[startXPosition];
                                        //dstRB = dst & 0x00FF00FF;
                                        //dstG = (dst >> 8) & 0xFF;
                                        //BufferData[startXPosition] =
                                        //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                        //    | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                        //    | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                        #region gamma apply
                                        dst = BufferData[startXPosition];
                                        dstG = (dst >> 8) & 0xFF;
                                        dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                        BufferData[startXPosition] =
                                            (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                            | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                            | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                            | (gammaLutBlue[(dstRB & 0x00FF)]));
                                        #endregion
                                        #endregion
                                        #endregion
                                    }
                                    #endregion

                                    // incre color index
                                    currentColorIndexScaled += incrementTranformedColorIndexScaled;

                                    scLastCoverage = currentCoverage;
                                    scLastX = currentCellData.X;

                                    // move to next cell
                                    currentCellData = currentCellData.Next;
                                } while (currentCellData != null);
                                #endregion
                            }
                        }
                    }
                    #endregion
                    #endregion
                }//GradientStyle.Pad mode
            }// no blending color
            else
            {// has blending color
                if (paint.Style != GradientStyle.Pad)
                {
                    #region optimized for reflect and repeat mode
                    incrementTranformedColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                    if (incrementTranformedColorIndexScaled < 0)
                    {
                        incrementTranformedColorIndexScaled = ColorIndexIncludeIncrementDoubleScale - incrementTranformedColorIndexScaled;
                    }
                    #endregion
                    // when no need to blending, when draw a horizontal line
                    // do not need check the back color, alway setup
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;

                        if (rows[startRowIndex] != null)
                        {
                            #region transform for row
                            currentColorIndexScaled = (int)
                                (currentYTransformed * ColorIndexIncludeIncrementScale);
                            if (currentColorIndexScaled < 0)
                            {
                                currentColorIndexScaled += ColorIndexIncludeIncrementDoubleScale;
                            }
                            currentYTransformed += startRowIncrement;
                            #endregion

                            // get first cell in current row
                            currentCellData = rows[startRowIndex].First;
                            if (currentCellData != null)
                            {
                                #region fill current row
                                do
                                {
                                    currentArea = currentCellData.Area;
                                    #region blend horizontal line
                                    if ((currentCellData.X > scLastX + 1))
                                    {
                                        if (scLastCoverage != 0)
                                        {
                                            // fast bit absolute
                                            scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);
                                            #region non-zero checking code
                                            if (scLastCoverage > 255) scLastCoverage = 255;
                                            #endregion

                                            #region BLEND HORIZONTAL LINE
                                            // calculate start and end position
                                            startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                            lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                            while (startXPosition < lastXPosition)
                                            {
                                                colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift];
                                                currentColorIndexScaled += incrementTranformedColorIndexScaled;
                                                calculatedCoverage = (byte)(colorData >> 24);
                                                calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);

                                                if (calculatedCoverage >= 254)
                                                {
                                                    BufferData[startXPosition] = colorData;
                                                }
                                                else
                                                {
                                                    #region blend here
                                                    //dst = BufferData[startXPosition];
                                                    //dstRB = dst & 0x00FF00FF;
                                                    //dstG = (dst >> 8) & 0xFF;

                                                    //BufferData[startXPosition] =
                                                    //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                    //    | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                    //    | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                    #region gamma apply
                                                    dst = BufferData[startXPosition];
                                                    dstG = (dst >> 8) & 0xFF;
                                                    dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                                    BufferData[startXPosition] =
                                                        (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                        | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                                        | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                                        | ((uint)gammaLutBlue[(dstRB & 0x00FF)]));
                                                    #endregion

                                                    #endregion
                                                }
                                                startXPosition++;
                                                currentColorIndexScaled++;
                                            }
                                            #endregion
                                        }
                                        else
                                        {
                                            // incre color index
                                            currentColorIndexScaled += (currentCellData.X - scLastX - 1) * incrementTranformedColorIndexScaled;
                                        }
                                    }
                                    #endregion

                                    currentCoverage += currentCellData.Coverage;

                                    #region blend the current cell
                                    tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                                    if (tempCover != 0)
                                    {
                                        // fast bit absolute
                                        tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                        #region non-zero checking code
                                        if (tempCover > 255) tempCover = 255;
                                        #endregion

                                        colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift];

                                        calculatedCoverage = (byte)(colorData >> 24);

                                        #region blend pixel
                                        tempCover = (int)((tempCover * calculatedCoverage) >> 8);
                                        //if (tempCover > 255) tempCover = 255;
                                        calculatedCoverage = (byte)tempCover;

                                        startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                        #region blend here
                                        //dst = BufferData[startXPosition];
                                        //dstRB = dst & 0x00FF00FF;
                                        //dstG = (dst >> 8) & 0xFF;
                                        //BufferData[startXPosition] =
                                        //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                        //    | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                        //    | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                        #region gamma apply
                                        dst = BufferData[startXPosition];
                                        dstG = (dst >> 8) & 0xFF;
                                        dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                        BufferData[startXPosition] =
                                            (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                            | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                            | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                            | (gammaLutBlue[(dstRB & 0x00FF)]));
                                        #endregion

                                        #endregion
                                        #endregion
                                    }
                                    #endregion

                                    // incre color index
                                    currentColorIndexScaled += incrementTranformedColorIndexScaled;

                                    scLastCoverage = currentCoverage;
                                    scLastX = currentCellData.X;

                                    // move to next cell
                                    currentCellData = currentCellData.Next;
                                } while (currentCellData != null);
                                #endregion
                            }
                        }
                    }
                    #endregion
                }
                else
                {
                    #region GradientStyle.Pad

                    // when no need to blending, when draw a horizontal line
                    // do not need check the back color, alway setup
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;

                        if (rows[startRowIndex] != null)
                        {
                            #region transform for row
                            currentColorIndexScaled = (int)
                                (currentYTransformed * ColorIndexIncludeIncrementScale);
                            //if (currentColorIndexScaled < 0)
                            //{
                            //    currentColorIndexScaled += ColorIndexIncludeIncrementDoubleScale;
                            //}
                            currentYTransformed += startRowIncrement;
                            #endregion

                            // get first cell in current row
                            currentCellData = rows[startRowIndex].First;
                            if (currentCellData != null)
                            {
                                #region fill current row
                                do
                                {
                                    currentArea = currentCellData.Area;
                                    #region blend horizontal line
                                    if ((currentCellData.X > scLastX + 1))
                                    {
                                        if (scLastCoverage != 0)
                                        {
                                            // fast bit absolute
                                            scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);
                                            #region non-zero checking code
                                            if (scLastCoverage > 255) scLastCoverage = 255;
                                            #endregion

                                            #region BLEND HORIZONTAL LINE
                                            // calculate start and end position
                                            startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                            lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                            while (startXPosition < lastXPosition)
                                            {
                                                //colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift];
                                                colorData = builtColors[
                                                    currentColorIndexScaled < 0 ?
                                                    0 :
                                                    (currentColorIndexScaled > ColorIndexIncludeIncrementScale ?
                                                    255 :
                                                    currentColorIndexScaled >> IncrementColorIndexShift)];
                                                currentColorIndexScaled += incrementTranformedColorIndexScaled;
                                                calculatedCoverage = (byte)(colorData >> 24);
                                                calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);

                                                if (calculatedCoverage >= 254)
                                                {
                                                    BufferData[startXPosition] = colorData;
                                                }
                                                else
                                                {
                                                    #region blend here
                                                    //dst = BufferData[startXPosition];
                                                    //dstRB = dst & 0x00FF00FF;
                                                    //dstG = (dst >> 8) & 0xFF;

                                                    //BufferData[startXPosition] =
                                                    //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                    //    | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                    //    | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                    #region gamma apply
                                                    dst = BufferData[startXPosition];
                                                    dstG = (dst >> 8) & 0xFF;
                                                    dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                                    BufferData[startXPosition] =
                                                        (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                        | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                                        | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                                        | ((uint)gammaLutBlue[(dstRB & 0x00FF)]));
                                                    #endregion

                                                    #endregion
                                                }
                                                startXPosition++;
                                                currentColorIndexScaled++;
                                            }
                                            #endregion
                                        }
                                        else
                                        {
                                            // incre color index
                                            currentColorIndexScaled += (currentCellData.X - scLastX - 1) * incrementTranformedColorIndexScaled;
                                        }
                                    }
                                    #endregion

                                    currentCoverage += currentCellData.Coverage;

                                    #region blend the current cell
                                    tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                                    if (tempCover != 0)
                                    {
                                        // fast bit absolute
                                        tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                        #region non-zero checking code
                                        if (tempCover > 255) tempCover = 255;
                                        #endregion

                                        colorData = builtColors[
                                            currentColorIndexScaled < 0 ?
                                                0 :
                                            (currentColorIndexScaled > ColorIndexIncludeIncrementScale ?
                                                255 :
                                                currentColorIndexScaled >> IncrementColorIndexShift)];

                                        calculatedCoverage = (byte)(colorData >> 24);

                                        #region blend pixel
                                        tempCover = (int)((tempCover * calculatedCoverage) >> 8);
                                        //if (tempCover > 255) tempCover = 255;
                                        calculatedCoverage = (byte)tempCover;

                                        startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                        #region blend here
                                        //dst = BufferData[startXPosition];
                                        //dstRB = dst & 0x00FF00FF;
                                        //dstG = (dst >> 8) & 0xFF;
                                        //BufferData[startXPosition] =
                                        //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                        //    | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                        //    | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                        #region gamma apply
                                        dst = BufferData[startXPosition];
                                        dstG = (dst >> 8) & 0xFF;
                                        dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                        BufferData[startXPosition] =
                                            (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                            | ((uint)(gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                            | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                            | ((uint)gammaLutBlue[(dstRB & 0x00FF)]));
                                        #endregion

                                        #endregion
                                        #endregion
                                    }
                                    #endregion

                                    // incre color index
                                    currentColorIndexScaled += incrementTranformedColorIndexScaled;

                                    scLastCoverage = currentCoverage;
                                    scLastX = currentCellData.X;

                                    // move to next cell
                                    currentCellData = currentCellData.Next;
                                } while (currentCellData != null);
                                #endregion
                            }
                        }
                    }
                    #endregion
                    #endregion
                }
            }//has blending color

            #endregion
        }
        /// <summary>
        /// Fill to buffer base rows data information using non-zero rule
        /// </summary>
        /// <param name="paint">linear gradient object</param>
        /// <param name="rows">row data information</param>
        /// <param name="startRowIndex">start row index in row array need to draw</param>
        /// <param name="endRowIndex">end row index in end row array need to draw</param>
        /// <param name="isForward">is diagonal gradient is forward</param>
        void OnFillingDiagonalNonZero(
            LinearGradient paint,
            uint opacity,
            RowData[] rows,
            int startRowIndex,
            int endRowIndex,
            bool isForward)
        {

            #region Explain for fomula

            /*
             * CALCULATION NEED FOLLOWING VALUES
             * 1/ INCREMENT
             * increment, when x from n to n+1 , 
             * index of color will increase from
             * f(n) to f(n) + increment
             * 
             * this increment value is calculated by
             * Linear from A to B
             * A              C      B'
             * *  *  *  *   *  *  *
             *    *         *    *
             *       *      *   *
             *          *   *  *
             *              * B
             * AC = w of the rect
             * BB' |_ AB
             * So AB' = (AB * AB)/AC = d * d / w
             * And increment is increment = 256 / AB'
             * it mean when x go from A to B'
             * color index will increase from 0=>255 ( 256 steps)
             * 
             * 
             * 2/ DISTANCE
             *              (x3,y3)
             *                *                  
             *               *
             *              *
             *             *
             *            *
             *           *
             *          *
             *  (x1,y1)*
             *               *
             *                     *
             *                           *
             *                         (x2,y2)
             *                    
             * x3,y3 can be calculated by following fomula
             *      x3 = x1 - height of paint = x1 - ( y2- y1);
             *      y3 = y1 + width of paint = y1 + ( x2 - x1);
             *      
             * to determine color at point(x,y) to line (x1,y1)-(x3,y3)
             * from this distance we can determine the color at this 
             * point by lookup to color array
             * 
             * distance = ((x - x3) * (y3-y1)
             *            - ( y - y3) * (x3 -x1))/(distance from start and end point of paint);
             */
            #endregion

            #region Pre-process
            double x1 = 0;
            double y1 = 0;
            double x2 = 0;
            double y2 = 0;
            if (isForward)
            {
                x1 = paint.StartX;
                y1 = paint.StartY;
                x2 = paint.EndX;
                y2 = paint.EndY;
            }
            else
            {
                x1 = paint.EndX;
                y1 = paint.StartY;

                x2 = paint.StartX;
                y2 = paint.EndY;
            }

            double widthOfPaint = x2 - x1;
            double heightOfPaint = y2 - y1;
            //note: start and end point is random
            // start not always on top-left
            // so width of paint and height of paint may be negative
            if (widthOfPaint == 0)
            {
                // this will change to vertical
                OnFillingVerticalNonZero(paint, opacity, rows, startRowIndex, endRowIndex);
                return;
            }
            else if (heightOfPaint == 0)
            {
                // this will change to horizontal
                OnFillingHorizontalNonZero(paint, opacity, rows, startRowIndex, endRowIndex);
                return;
            }
            #endregion

            #region calculate the increasement

            double x3 = x1 - heightOfPaint;
            double y3 = y1 + widthOfPaint;

            double lengthOfPaint = Math.Sqrt((widthOfPaint * widthOfPaint) + (heightOfPaint * heightOfPaint));
            //int distanceOfPaintScaled = (int)(distanceOfPaint * DistanceScale);
            double incrementColorIndex = (double)(widthOfPaint * ColorIndexScale) / (lengthOfPaint * lengthOfPaint);

            // increment by distance scale
            // increment may be greater than 512, but in reflect,repeat mode, 
            // just modulo it
            // get the remain when divide by 512
            // incrementColorIndex = incrementColorIndex - (((int)incrementColorIndex / ColorIndexDoubleScale) * ColorIndexDoubleScale); 

            //incrementX < 512, calculate incrementIndex  
            // ( that scale by 256 for approxiate calculation )
            int scaledIncrementColorIndex = (int)(incrementColorIndex * IncrementColorIndexScale);

            #endregion

            // now not need to check null or not
            uint[] builtColors = paint.GetLinearColors(opacity);

            #region private variable for filling
            int currentCoverage, scLastCoverage, scLastX = 0;
            int tempCover = 0;
            int currentArea = 0;
            int lastXPosition = 0;
            int startXPosition = 0;
            byte calculatedCoverage = 0;

            // this color index is scaled
            int currentColorIndexScaled = 0;

            CellData currentCellData = null;
            uint colorData = 0;
            uint dst, dstRB, dstG;
            double firstPointDistance = 0;
            #endregion

            #region optimization for color index

            // the ORIGIN fomula for each row, we need to calculate this
            //firstPointDistance = (((x3) * (y3 - y1) - (startRowIndex - y3) * (x3 - x1)) / distanceOfPaint);
            //// color index = (distance from point to line => scaled) * 256/ (distance of paint scaled)
            //currentColorIndexScaled =
            //    (int)((firstPointDistance * ColorIndexIncludeIncrementScale / distanceOfPaint));
            //    currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; // mod ( 512 << 8)


            // now we need calculate for first time only and after a row, we need to add and small value
            //firstPointDistance  is x value when line cut the horizontal at position startRowIndex
            //firstPointDistance = (((x3) * (y3 - y1) - (startRowIndex - y3) * (x3 - x1)) /(lengthOfPaint));
            // y = slope * x + beta
            //=> slope * x - y + beta = 0
            double slope = (y3 - y1) / (x3 - x1);
            double beta = (y3 - slope * x3);
            // fomula to calculate distance from point to line a*x + b*y + c= 0
            // is d = (a*x1 + b*y1 + c) / sqrt(a*a + b*b)
            // in this case d = (slope * x1 + (-1) * y1 + beta) / sqrt ( slope * slope + (-1) * (-1))
            //firstPointDistance = (-startRowIndex + beta) / Math.Sqrt(slope * slope + 1);


            //http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
            firstPointDistance = ((x3 - x1) * (y1 - startRowIndex) - (x1 - 0) * (y3 - y1))
                / lengthOfPaint;

            int startOfRowIndex = (int)((firstPointDistance * ColorIndexIncludeIncrementScale / lengthOfPaint));
            int rowColorIndexIncrementScaled = (int)(((-(x3 - x1) / lengthOfPaint) * ColorIndexIncludeIncrementScale / lengthOfPaint));

            #endregion

            #region FILLING
            if (paint.Ramp.NoBlendingColor)
            {
                if (paint.Style != GradientStyle.Pad)
                {
                    #region GradientStyle.Reflect || GradientStyle.Repeat
                    // in case reflect and repeat, we don't care value that out of range
                    startOfRowIndex &= ColorIndexIncludeIncrementDoubleMask;
                    rowColorIndexIncrementScaled &= ColorIndexIncludeIncrementDoubleMask;
                    scaledIncrementColorIndex &= ColorIndexIncludeIncrementDoubleMask;

                    #region filling without blend for horizontal lines
                    // when no need to blending, when draw a horizontal line
                    // do not need check the back color, alway setup
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;

                        if (rows[startRowIndex] != null)
                        {
                            // get first cell in current row
                            currentCellData = rows[startRowIndex].First;
                            if (currentCellData != null)
                            {
                                // calculate the first cell color index
                                #region second way to implement color index
                                currentColorIndexScaled = startOfRowIndex;
                                #endregion

                                #region fill current row
                                do
                                {
                                    currentArea = currentCellData.Area;

                                    #region blend horizontal line
                                    if ((currentCellData.X > scLastX + 1))
                                    {
                                        if (scLastCoverage != 0)
                                        {
                                            // fast bit absolute
                                            scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);
                                            #region non-zero checking code
                                            if (scLastCoverage > 255) scLastCoverage = 255;
                                            #endregion
                                            #region BLEND HORIZONTAL LINE
                                            // calculate start and end position
                                            startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                            lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                            // get current color index value
                                            if (scLastCoverage >= 254)
                                            {
                                                while (startXPosition < lastXPosition)
                                                {
                                                    BufferData[startXPosition] = builtColors[currentColorIndexScaled < 0 ?
                                                        (currentColorIndexScaled >> IncrementColorIndexShift) + 512 :
                                                        (currentColorIndexScaled >> IncrementColorIndexShift)];
                                                    startXPosition++;
                                                    // increase current color index
                                                    currentColorIndexScaled += scaledIncrementColorIndex;
                                                    currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                                                }
                                            }
                                            else
                                            {
                                                calculatedCoverage = (byte)scLastCoverage;
                                                while (startXPosition < lastXPosition)
                                                {
                                                    dst = BufferData[startXPosition];
                                                    colorData = builtColors[currentColorIndexScaled < 0 ?
                                                            (currentColorIndexScaled >> IncrementColorIndexShift) + 512 :
                                                            (currentColorIndexScaled >> IncrementColorIndexShift)];
                                                    dstRB = dst & 0x00FF00FF;
                                                    dstG = (dst >> 8) & 0xFF;
                                                    BufferData[startXPosition] =
                                                        (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                        | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                        | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                    startXPosition++;
                                                    // increase the current color index
                                                    currentColorIndexScaled += scaledIncrementColorIndex;
                                                    currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                                                }
                                            }
                                            #endregion
                                        }
                                        else
                                        {
                                            // not filling but must set and increase the color index
                                            currentColorIndexScaled += (currentCellData.X - scLastX - 1) * scaledIncrementColorIndex;
                                            currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                                        }
                                    }
                                    #endregion

                                    currentCoverage += currentCellData.Coverage;

                                    #region blend the current cell
                                    // fast absolute
                                    tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                                    if (tempCover != 0)
                                    {
                                        // fast bit absolute
                                        tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                        #region non-zero checking code
                                        if (tempCover > 255) tempCover = 255;
                                        #endregion

                                        // get current color data
                                        #region blend pixel
                                        //tempCover = (int)((tempCover * colorAlpha) >> 8);
                                        ////if (tempCover > 255) tempCover = 255;
                                        calculatedCoverage = (byte)tempCover;

                                        startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                        #region blend here
                                        dst = BufferData[startXPosition];
                                        colorData = builtColors[currentColorIndexScaled < 0 ?
                                                (currentColorIndexScaled >> IncrementColorIndexShift) + 512 :
                                                (currentColorIndexScaled >> IncrementColorIndexShift)];
                                        dstRB = dst & 0x00FF00FF;
                                        dstG = (dst >> 8) & 0xFF;

                                        BufferData[startXPosition] =
                                            (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                            | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                            | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                        #endregion

                                        #endregion
                                    }
                                    #endregion

                                    // alway increment color index
                                    currentColorIndexScaled += scaledIncrementColorIndex;
                                    currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;

                                    // assign value for next loop
                                    scLastCoverage = currentCoverage;
                                    scLastX = currentCellData.X;

                                    // move to next cell
                                    currentCellData = currentCellData.Next;
                                } while (currentCellData != null);
                                #endregion
                            }
                        }
                        #region each row we need increase the value of color index
                        startOfRowIndex += rowColorIndexIncrementScaled;
                        startOfRowIndex &= ColorIndexIncludeIncrementDoubleMask;
                        #endregion
                    }
                    #endregion
                    #endregion
                }//Reflect or Repeat mode
                else
                {//Pad mode
                    #region GradientStyle.Pad
                    // when no need to blending, when draw a horizontal line
                    // do not need check the back color, alway setup
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;

                        if (rows[startRowIndex] != null)
                        {
                            // get first cell in current row
                            currentCellData = rows[startRowIndex].First;
                            if (currentCellData != null)
                            {
                                // calculate the first cell color index
                                #region second way to implement color index
                                currentColorIndexScaled = startOfRowIndex;
                                #endregion

                                #region fill current row
                                do
                                {
                                    currentArea = currentCellData.Area;

                                    #region blend horizontal line
                                    if ((currentCellData.X > scLastX + 1))
                                    {
                                        if (scLastCoverage != 0)
                                        {
                                            // fast bit absolute
                                            scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);

                                            #region non-zero checking code
                                            if (scLastCoverage > 255) scLastCoverage = 255;
                                            #endregion

                                            #region BLEND HORIZONTAL LINE
                                            // calculate start and end position
                                            startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                            lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                            // get current color index value
                                            if (scLastCoverage >= 254)
                                            {
                                                while (startXPosition < lastXPosition)
                                                {
                                                    BufferData[startXPosition] = builtColors[
                                                        currentColorIndexScaled < 0 ?
                                                            0 :
                                                        (currentColorIndexScaled > ColorIndexIncludeIncrementScale ?
                                                            255 :
                                                            (currentColorIndexScaled >> IncrementColorIndexShift))];
                                                    startXPosition++;
                                                    // increase current color index
                                                    currentColorIndexScaled += scaledIncrementColorIndex;
                                                }
                                            }
                                            else
                                            {
                                                calculatedCoverage = (byte)scLastCoverage;
                                                while (startXPosition < lastXPosition)
                                                {
                                                    colorData = builtColors[
                                                        currentColorIndexScaled < 0 ?
                                                            0 :
                                                        (currentColorIndexScaled > ColorIndexIncludeIncrementScale ?
                                                            255 :
                                                            (currentColorIndexScaled >> IncrementColorIndexShift))];
                                                    #region blend here
                                                    dst = BufferData[startXPosition];
                                                    dstRB = dst & 0x00FF00FF;
                                                    dstG = (dst >> 8) & 0xFF;
                                                    BufferData[startXPosition] =
                                                        (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                        | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                        | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                    #endregion
                                                    startXPosition++;
                                                    // increase the current color index
                                                    currentColorIndexScaled += scaledIncrementColorIndex;
                                                }
                                            }
                                            #endregion
                                        }
                                        else
                                        {
                                            // not filling but must set and increase the color index
                                            currentColorIndexScaled += (currentCellData.X - scLastX - 1) * scaledIncrementColorIndex;
                                        }
                                    }
                                    #endregion

                                    currentCoverage += currentCellData.Coverage;

                                    #region blend the current cell
                                    // fast absolute
                                    tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                                    if (tempCover != 0)
                                    {
                                        // fast bit absolute
                                        tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                        #region non-zero checking code
                                        if (tempCover > 255) tempCover = 255;
                                        #endregion
                                        // get current color data
                                        #region blend pixel
                                        calculatedCoverage = (byte)tempCover;

                                        startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                        #region blend here
                                        dst = BufferData[startXPosition];
                                        colorData = builtColors[
                                            currentColorIndexScaled < 0 ?
                                                0 :
                                            (currentColorIndexScaled > ColorIndexIncludeIncrementScale ?
                                                255 :
                                                (currentColorIndexScaled >> IncrementColorIndexShift))];

                                        dstRB = dst & 0x00FF00FF;
                                        dstG = (dst >> 8) & 0xFF;
                                        BufferData[startXPosition] =
                                            (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                            | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                            | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                        #endregion
                                        #endregion


                                    }
                                    #endregion

                                    // alway increment color index
                                    currentColorIndexScaled += scaledIncrementColorIndex;

                                    // assign value for next loop
                                    scLastCoverage = currentCoverage;
                                    scLastX = currentCellData.X;

                                    // move to next cell
                                    currentCellData = currentCellData.Next;
                                } while (currentCellData != null);
                                #endregion
                            }
                        }
                        #region each row we need increase the value of color index
                        startOfRowIndex += rowColorIndexIncrementScaled;
                        #endregion
                    }
                    #endregion
                }//Pad mode
            }//paint.Ramp.NoBlendingColor
            else
            {//has blending color
                // blending include alpha of built color
                if (paint.Style != GradientStyle.Pad)
                {
                    #region GradientStyle.Reflect || GradientStyle.Repeat
                    // in case reflect and repeat, we don't care value that out of range
                    startOfRowIndex &= ColorIndexIncludeIncrementDoubleMask;
                    rowColorIndexIncrementScaled &= ColorIndexIncludeIncrementDoubleMask;
                    // when no need to blending, when draw a horizontal line
                    // do not need check the back color, alway setup
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;

                        if (rows[startRowIndex] != null)
                        {
                            // get first cell in current row
                            currentCellData = rows[startRowIndex].First;
                            if (currentCellData != null)
                            {
                                // calculate the first cell color index
                                #region second way to implement color index
                                currentColorIndexScaled = startOfRowIndex;
                                #endregion

                                #region fill current row
                                do
                                {
                                    currentArea = currentCellData.Area;
                                    #region blend horizontal line
                                    if ((currentCellData.X > scLastX + 1))
                                    {
                                        if (scLastCoverage != 0)
                                        {
                                            // fast bit absolute
                                            scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);

                                            #region non-zero checking code
                                            if (scLastCoverage > 255) scLastCoverage = 255;
                                            #endregion

                                            #region BLEND HORIZONTAL LINE
                                            // calculate start and end position
                                            startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                            lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                            while (startXPosition < lastXPosition)
                                            {
                                                colorData = builtColors[currentColorIndexScaled < 0 ?
                                                        (currentColorIndexScaled >> IncrementColorIndexShift) + 512 :
                                                        (currentColorIndexScaled >> IncrementColorIndexShift)];

                                                // get current color index value
                                                calculatedCoverage = (byte)(((colorData >> 24) * scLastCoverage) >> 8);

                                                #region blend here
                                                dst = BufferData[startXPosition];
                                                dstRB = dst & 0x00FF00FF;
                                                dstG = (dst >> 8) & 0xFF;
                                                BufferData[startXPosition] =
                                                    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                    | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                    | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                startXPosition++;
                                                #endregion

                                                // increase the current color index
                                                currentColorIndexScaled += scaledIncrementColorIndex;
                                                currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                                            }
                                            #endregion
                                        }
                                        else
                                        {
                                            // not filling but must set and increase the color index
                                            currentColorIndexScaled += (currentCellData.X - scLastX - 1) * scaledIncrementColorIndex;
                                            currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                                        }
                                    }
                                    #endregion

                                    currentCoverage += currentCellData.Coverage;

                                    #region blend the current cell
                                    // fast absolute
                                    tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                                    if (tempCover != 0)
                                    {
                                        // fast bit absolute
                                        tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                        #region non-zero checking code
                                        if (tempCover > 255) tempCover = 255;
                                        #endregion

                                        // get current color data
                                        #region blend pixel
                                        //tempCover = (int)((tempCover * colorAlpha) >> 8);
                                        ////if (tempCover > 255) tempCover = 255;
                                        //calculatedCoverage = (byte)tempCover;

                                        startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                        #region blend here
                                        colorData = builtColors[currentColorIndexScaled < 0 ?
                                                (currentColorIndexScaled >> IncrementColorIndexShift) + 512 :
                                                (currentColorIndexScaled >> IncrementColorIndexShift)];
                                        calculatedCoverage = (byte)(((colorData >> 24) * tempCover) >> 8);
                                        dst = BufferData[startXPosition];
                                        dstRB = dst & 0x00FF00FF;
                                        dstG = (dst >> 8) & 0xFF;

                                        BufferData[startXPosition] =
                                            (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                            | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                            | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                        #endregion

                                        #endregion
                                    }
                                    #endregion

                                    // alway increment color index
                                    currentColorIndexScaled += scaledIncrementColorIndex;
                                    currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;

                                    // assign value for next loop
                                    scLastCoverage = currentCoverage;
                                    scLastX = currentCellData.X;

                                    // move to next cell
                                    currentCellData = currentCellData.Next;
                                } while (currentCellData != null);
                                #endregion
                            }
                        }

                        #region each row we need increase the value of color index
                        startOfRowIndex += rowColorIndexIncrementScaled;
                        startOfRowIndex &= ColorIndexIncludeIncrementDoubleMask;
                        #endregion
                    }
                    #endregion
                    #endregion
                }//Reflect or Repeat mode
                else
                {//Pad mode
                    #region GradientStyle.Pad
                    // when no need to blending, when draw a horizontal line
                    // do not need check the back color, alway setup
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;

                        if (rows[startRowIndex] != null)
                        {
                            // get first cell in current row
                            currentCellData = rows[startRowIndex].First;
                            if (currentCellData != null)
                            {
                                // calculate the first cell color index
                                #region second way to implement color index
                                currentColorIndexScaled = startOfRowIndex;
                                #endregion

                                #region fill current row
                                do
                                {
                                    currentArea = currentCellData.Area;

                                    #region blend horizontal line
                                    if ((currentCellData.X > scLastX + 1))
                                    {
                                        if (scLastCoverage != 0)
                                        {
                                            // fast bit absolute
                                            scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);

                                            #region non-zero checking code
                                            if (scLastCoverage > 255) scLastCoverage = 255;
                                            #endregion

                                            #region BLEND HORIZONTAL LINE
                                            // calculate start and end position
                                            startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                            lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                            // get current color index value

                                            while (startXPosition < lastXPosition)
                                            {
                                                colorData = builtColors[currentColorIndexScaled < 0 ?
                                                    0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 :
                                                    (currentColorIndexScaled >> IncrementColorIndexShift))];
                                                calculatedCoverage = (byte)(((colorData >> 24) * scLastCoverage) >> 8);

                                                #region blend here
                                                dst = BufferData[startXPosition];
                                                dstRB = dst & 0x00FF00FF;
                                                dstG = (dst >> 8) & 0xFF;
                                                BufferData[startXPosition] =
                                                    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                    | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                    | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                #endregion

                                                startXPosition++;
                                                // increase the current color index
                                                currentColorIndexScaled += scaledIncrementColorIndex;
                                                //currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                                            }

                                            #endregion
                                        }
                                        else
                                        {
                                            // not filling but must set and increase the color index
                                            currentColorIndexScaled += (currentCellData.X - scLastX - 1) * scaledIncrementColorIndex;
                                            //currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask;
                                        }
                                    }
                                    #endregion

                                    currentCoverage += currentCellData.Coverage;

                                    #region blend the current cell
                                    // fast absolute
                                    tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                                    if (tempCover != 0)
                                    {
                                        // fast bit absolute
                                        tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                        #region non-zero checking code
                                        if (tempCover > 255) tempCover = 255;
                                        #endregion

                                        // get current color data
                                        #region blend pixel
                                        //calculatedCoverage = (byte)tempCover;

                                        startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                        #region blend here
                                        colorData = builtColors[currentColorIndexScaled < 0 ?
                                                        0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 :
                                                        (currentColorIndexScaled >> IncrementColorIndexShift))];
                                        calculatedCoverage = (byte)(((colorData >> 24) * tempCover) >> 8);
                                        dst = BufferData[startXPosition];
                                        dstRB = dst & 0x00FF00FF;
                                        dstG = (dst >> 8) & 0xFF;

                                        BufferData[startXPosition] =
                                            (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                            | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                            | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                        #endregion

                                        #endregion
                                    }
                                    #endregion

                                    // alway increment color index
                                    currentColorIndexScaled += scaledIncrementColorIndex;

                                    // assign value for next loop
                                    scLastCoverage = currentCoverage;
                                    scLastX = currentCellData.X;

                                    // move to next cell
                                    currentCellData = currentCellData.Next;
                                } while (currentCellData != null);
                                #endregion
                            }
                        }

                        #region each row we need increase the value of color index
                        startOfRowIndex += rowColorIndexIncrementScaled;
                        #endregion
                    }
                    #endregion
                }//Pad mode
            }//has blending color

            #endregion
        }
        /// <summary>
        /// Fill to buffer base rows data information using non-zero rule
        /// </summary>
        /// <param name="paint">linear gradient object</param>
        /// <param name="rows">row data information</param>
        /// <param name="startRowIndex">start row index in row array need to draw</param>
        /// <param name="endRowIndex">end row index in end row array need to draw</param>
        void OnFillingHorizontalNonZero(
            LinearGradient paint,
            uint opacity,
            RowData[] rows,
            int startRowIndex,
            int endRowIndex)
        {
            // now not need to check null or not
            uint[] builtColors = paint.GetLinearColors(opacity);

            /*  Base on startX, endX, we need build fixedColor array
             *  contain width-count elements. So that, at a column,
             *  we can lookup color for that column.    */

            #region Build fixed color
            double startX = paint.StartX;
            double endX = paint.EndX;

            // width of this
            int width = CurrentEndXIndex - CurrentStartXIndex + 1;
            uint[] fixedColor = new uint[width];
            int distanceScaled = (int)(Math.Abs(startX - endX) * DistanceScale);
            if (distanceScaled == 0)
            {
                FillingException.Publish(typeof(LinearGradient), "Start point and end point are too close");
                return;
            }
            #region build fixed-color array
            if (paint.Style == GradientStyle.Pad)
            {
                #region GradientStyle.Pad
                int startXScaled = (int)(startX * DistanceScale);
                int startFixedIndex = (((
                        (((width + CurrentStartXIndex) << DistanceShift) - startXScaled)
                        << ColorIndexShift) / distanceScaled)) << IncrementColorIndexShift;
                int colorIncrement = (DistanceScale * ColorIndexIncludeIncrementScale) / distanceScaled;
                if (endX < startX)
                {
                    colorIncrement = -colorIncrement;
                    startFixedIndex = -startFixedIndex;
                }
                while (width-- > 0)
                {
                    fixedColor[width] = builtColors[
                        startFixedIndex < 0 ?
                            0 :
                        (startFixedIndex > ColorIndexIncludeIncrementScale ?
                            255 :
                            (startFixedIndex >> IncrementColorIndexShift))];
                    startFixedIndex -= colorIncrement;
                }
                #endregion
            }
            else
            {
                #region GradientStyle.Repeat || GradientStyle.Reflect
                int startXScaled = (int)(startX * DistanceScale);
                int startFixedIndex = (((
                    (((width + CurrentStartXIndex) << DistanceShift) - startXScaled)
                    << ColorIndexShift) / distanceScaled)) << IncrementColorIndexShift;
                int colorIncrement = (DistanceScale * ColorIndexIncludeIncrementScale) / distanceScaled;
                if (endX < startX)
                {
                    colorIncrement = -colorIncrement;
                }
                startFixedIndex &= ColorIndexIncludeIncrementDoubleMask;
                while (width-- > 0)
                {
                    fixedColor[width] = builtColors[
                        startFixedIndex < 0 ?
                            (startFixedIndex >> IncrementColorIndexShift) + 512 :
                            (startFixedIndex >> IncrementColorIndexShift)];
                    startFixedIndex -= colorIncrement;
                    startFixedIndex &= ColorIndexIncludeIncrementDoubleMask;
                }
                #endregion
            }
            #endregion

            #endregion

            #region private variable for filling
            int currentCoverage, scLastCoverage, scLastX = 0;
            int tempCover = 0;
            int currentArea = 0;
            int lastXPosition = 0;
            int startXPosition = 0;
            byte calculatedCoverage = 0;
            int currentColorIndexValue = 0;
            CellData currentCellData = null;
            uint colorData = 0;
            uint dst, dstRB, dstG;
            #endregion

            #region FILLING
            if (paint.Ramp.NoBlendingColor)
            {
                #region filling without blend for horizontal lines
                // when no need to blending, when draw a horizontal line
                // do not need check the back color, alway setup
                startRowIndex--;
                while (++startRowIndex <= endRowIndex)
                {
                    currentCoverage = scLastCoverage = scLastX = 0;

                    if (rows[startRowIndex] != null)
                    {
                        // get first cell in current row
                        currentCellData = rows[startRowIndex].First;
                        if (currentCellData != null)
                        {
                            #region fill current row
                            do
                            {
                                currentArea = currentCellData.Area;

                                #region blend horizontal line
                                if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0))
                                {
                                    // fast bit absolute
                                    scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);

                                    #region non-zero checking code
                                    if (scLastCoverage > 255) scLastCoverage = 255;
                                    #endregion

                                    if (scLastCoverage != 0)
                                    {
                                        #region BLEND HORIZONTAL LINE
                                        // calculate start and end position
                                        startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                        lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                        // get current color index value
                                        currentColorIndexValue = scLastX + 1 - CurrentStartXIndex;
                                        if (scLastCoverage >= 255)
                                        {
                                            while (startXPosition < lastXPosition)
                                            {
                                                BufferData[startXPosition++] = fixedColor[currentColorIndexValue++];
                                            }
                                        }
                                        else
                                        {
                                            while (startXPosition < lastXPosition)
                                            {
                                                colorData = fixedColor[currentColorIndexValue];
                                                calculatedCoverage = (byte)((colorData >> 24));
                                                calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);

                                                if (calculatedCoverage >= 255)
                                                {
                                                    BufferData[startXPosition] = colorData;
                                                }
                                                else
                                                {
                                                    #region blend here
                                                    dst = BufferData[startXPosition];
                                                    dstRB = dst & 0x00FF00FF;
                                                    dstG = (dst >> 8) & 0xFF;

                                                    BufferData[startXPosition] =
                                                        (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                        | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                        | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                    #endregion
                                                }
                                                startXPosition++;
                                                currentColorIndexValue++;
                                            }
                                        }
                                        #endregion
                                    }
                                }
                                #endregion

                                currentCoverage += currentCellData.Coverage;

                                #region blend the current cell
                                // fast absolute
                                tempCover = ((currentCoverage << 9) - currentArea) >> 9;

                                if (tempCover != 0)
                                {
                                    // fast bit absolute
                                    tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                    #region non-zero checking code
                                    if (tempCover > 255) tempCover = 255;
                                    #endregion

                                    // get current color data
                                    colorData = fixedColor[currentCellData.X - CurrentStartXIndex];
                                    calculatedCoverage = (byte)(colorData >> 24);

                                    #region blend pixel
                                    tempCover = (int)((tempCover * calculatedCoverage) >> 8);
                                    //if (tempCover > 255) tempCover = 255;
                                    calculatedCoverage = (byte)tempCover;

                                    startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                    #region blend here
                                    dst = BufferData[startXPosition];
                                    dstRB = dst & 0x00FF00FF;
                                    dstG = (dst >> 8) & 0xFF;

                                    BufferData[startXPosition] =
                                        (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                        | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                        | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                    #endregion

                                    #endregion
                                }
                                #endregion

                                scLastCoverage = currentCoverage;
                                scLastX = currentCellData.X;

                                // move to next cell
                                currentCellData = currentCellData.Next;
                            } while (currentCellData != null);
                            #endregion
                        }
                    }
                }
                #endregion
            }//paint.Ramp.NoBlendingColor
            else
            {//has blending color
                #region perform normal filling
                startRowIndex--;
                while (++startRowIndex <= endRowIndex)
                {
                    currentCoverage = scLastCoverage = scLastX = 0;

                    if (rows[startRowIndex] != null)
                    {
                        // get first cell in current row
                        currentCellData = rows[startRowIndex].First;
                        if (currentCellData != null)
                        {
                            #region fill current row
                            do
                            {
                                currentArea = currentCellData.Area;

                                #region blend horizontal line
                                if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0))
                                {
                                    // fast bit absolute
                                    scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);

                                    #region non-zero checking code
                                    if (scLastCoverage > 255) scLastCoverage = 255;
                                    #endregion

                                    if (scLastCoverage != 0)
                                    {
                                        #region BLEND HORIZONTAL LINE
                                        // calculate start and end position
                                        startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                        lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                        // get current color index value
                                        currentColorIndexValue = scLastX + 1 - CurrentStartXIndex;
                                        while (startXPosition < lastXPosition)
                                        {
                                            colorData = fixedColor[currentColorIndexValue];
                                            calculatedCoverage = (byte)(colorData >> 24);
                                            calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);

                                            if (calculatedCoverage >= 255)
                                            {
                                                BufferData[startXPosition] = colorData;
                                            }
                                            else
                                            {
                                                #region blend here
                                                dst = BufferData[startXPosition];
                                                dstRB = dst & 0x00FF00FF;
                                                dstG = (dst >> 8) & 0xFF;

                                                BufferData[startXPosition] =
                                                    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                    | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                    | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                #endregion
                                            }
                                            startXPosition++;
                                            currentColorIndexValue++;
                                        }
                                        #endregion
                                    }
                                }
                                #endregion

                                currentCoverage += currentCellData.Coverage;

                                #region blend the current cell
                                // fast absolute
                                tempCover = ((currentCoverage << 9) - currentArea) >> 9;

                                if (tempCover != 0)
                                {
                                    // fast bit absolute
                                    tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                    #region non-zero checking code
                                    if (tempCover > 255) tempCover = 255;
                                    #endregion

                                    // get current color data
                                    colorData = fixedColor[currentCellData.X - CurrentStartXIndex];
                                    calculatedCoverage = (byte)(colorData >> 24);

                                    #region blend pixel

                                    tempCover = (int)((tempCover * calculatedCoverage) >> 8);
                                    //if (tempCover > 255) tempCover = 255;
                                    calculatedCoverage = (byte)tempCover;
                                    startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                    #region blend here
                                    dst = BufferData[startXPosition];
                                    dstRB = dst & 0x00FF00FF;
                                    dstG = (dst >> 8) & 0xFF;

                                    BufferData[startXPosition] =
                                        (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                        | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                        | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                    #endregion

                                    #endregion
                                }
                                #endregion

                                scLastCoverage = currentCoverage;
                                scLastX = currentCellData.X;

                                // move to next cell
                                currentCellData = currentCellData.Next;
                            } while (currentCellData != null);
                            #endregion
                        }
                    }
                }
                #endregion
            }//has blending color
            #endregion
        }
        /// <summary>
        /// Fill to buffer base rows data information using non-zero rule
        /// </summary>
        /// <param name="paint">linear gradient object</param>
        /// <param name="rows">row data information</param>
        /// <param name="startRowIndex">start row index in row array need to draw</param>
        /// <param name="endRowIndex">end row index in end row array need to draw</param>
        /// <param name="gammaLutRed">gamma look up table for red</param>
        /// <param name="gammaLutGreen">gamma look up table for green</param>
        /// <param name="gammaLutBlue">gamma look up table for blue</param>
        void OnFillingVerticalEvenOdd(
            LinearGradient paint,
            uint opacity,
            RowData[] rows,
            int startRowIndex,
            int endRowIndex,
            byte[] gammaLutRed,
            byte[] gammaLutGreen,
            byte[] gammaLutBlue)
        {
            // now not need to check null or not
            uint[] builtColors = paint.GetLinearColors(opacity);

            /*Base on startX,endX, we need build fixedColor array
             * contain width count elements. So that, at a column, we
             * can lookup color for that column.
             */

            #region build fixed color
            double startY = paint.StartY;
            double endY = paint.EndY;

            // width of this
            int height = endRowIndex - startRowIndex + 1;
            uint[] fixedColor = new uint[height];
            int distanceScaled = (int)(Math.Abs(startY - endY) * DistanceScale);
            if (distanceScaled == 0)
            {
                FillingException.Publish(typeof(LinearGradient), "Start point and end point are too close");
                return;
            }
            #region building fixed color array
            if (paint.Style == GradientStyle.Pad)
            {
                #region GradientStyle.Pad
                int startFixedIndex = (((
                        (((height + startRowIndex) << DistanceShift) - (int)(startY * DistanceScale))
                        << ColorIndexShift) / distanceScaled)) << IncrementColorIndexShift;

                int colorIncrement = (DistanceScale * ColorIndexIncludeIncrementScale) / distanceScaled;
                if (endY < startY)
                {
                    colorIncrement = -colorIncrement;
                    startFixedIndex = -startFixedIndex;
                }
                while (height-- > 0)
                {
                    fixedColor[height] =
                        builtColors[startFixedIndex < 0 ?
                            0 :
                        (startFixedIndex > ColorIndexIncludeIncrementScale ?
                            255 :
                            (startFixedIndex >> IncrementColorIndexShift))];
                    startFixedIndex -= colorIncrement;
                }
                #endregion
            }
            else
            {
                #region GradientStyle.Repeat || GradientStyle.Reflect
                int startFixedIndex = (((
                        (((height + startRowIndex) << DistanceShift) - (int)(startY * DistanceScale))
                        << ColorIndexShift) / distanceScaled)) << IncrementColorIndexShift;
                int colorIncrement = (DistanceScale * ColorIndexIncludeIncrementScale) / distanceScaled;
                if (endY < startY)
                {
                    colorIncrement = -colorIncrement;
                }
                startFixedIndex &= ColorIndexIncludeIncrementDoubleMask;
                while (height-- > 0)
                {
                    fixedColor[height] = builtColors[
                        startFixedIndex < 0 ?
                            (startFixedIndex >> IncrementColorIndexShift) + 512 :
                            (startFixedIndex >> IncrementColorIndexShift)];
                    startFixedIndex -= colorIncrement;
                    startFixedIndex &= ColorIndexIncludeIncrementDoubleMask;
                }
                #endregion
            }
            #endregion

            #endregion

            #region private variable for filling
            int currentCoverage, scLastCoverage, scLastX = 0;
            int tempCover = 0;
            int currentArea = 0;
            int lastXPosition = 0;
            int startXPosition = 0;
            byte calculatedCoverage = 0;

            int currentColorIndexValue = 0;

            CellData currentCellData = null;
            uint colorData = 0;
            uint colorAlpha = 0;
            uint colorG = 0;
            uint colorRB = 0;

            uint dst, dstRB, dstG;
            #endregion

            #region FILLING
            if (paint.Ramp.NoBlendingColor)
            {
                // when no need to blending, when draw a horizontal line
                // do not need check the back color, alway setup
                #region filling without blend for horizontal lines
                startRowIndex--;
                while (++startRowIndex <= endRowIndex)
                {
                    currentCoverage = scLastCoverage = scLastX = 0;

                    if (rows[startRowIndex] != null)
                    {
                        #region calculate and get current color
                        colorData = fixedColor[currentColorIndexValue];
                        colorAlpha = (colorData >> 24);
                        colorG = (colorData & 0x0000FF00) >> 8;
                        colorRB = (colorData & 0x00FF00FF);
                        #endregion
                        // get first cell in current row
                        currentCellData = rows[startRowIndex].First;
                        if (currentCellData != null)
                        {
                            #region fill current row
                            do
                            {
                                currentArea = currentCellData.Area;
                                #region blend horizontal line
                                if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0))
                                {
                                    // fast bit absolute
                                    scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);
                                    //#region non-zero checking code
                                    //if (scLastCoverage > 255) scLastCoverage = 255;
                                    //#endregion
                                    #region even-odd change
                                    scLastCoverage &= 511;
                                    if (scLastCoverage > 256)
                                    {
                                        scLastCoverage = 512 - scLastCoverage;
                                    }
                                    #endregion

                                    #region BLEND HORIZONTAL LINE
                                    // calculate start and end position
                                    startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                    lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                    // get current color index value
                                    if (scLastCoverage >= 254)
                                    {
                                        while (startXPosition < lastXPosition)
                                        {
                                            BufferData[startXPosition++] = colorData;
                                        }
                                    }
                                    else
                                    {
                                        while (startXPosition < lastXPosition)
                                        {
                                            calculatedCoverage = (byte)((scLastCoverage * colorAlpha) >> 8);
                                            if (calculatedCoverage >= 254)
                                            {
                                                BufferData[startXPosition] = colorData;
                                            }
                                            else
                                            {
                                                #region blend here
                                                //dst = BufferData[startXPosition];
                                                //dstRB = dst & 0x00FF00FF;
                                                //dstG = (dst >> 8) & 0xFF;

                                                //BufferData[startXPosition] =
                                                //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                //    | (uint)((((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                //    | (uint)(((((colorRB - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);

                                                #region gamma apply
                                                dst = BufferData[startXPosition];
                                                dstG = (dst >> 8) & 0xFF;
                                                dstRB = ((((colorRB - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                                BufferData[startXPosition] =
                                                    (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                    | (((uint)gammaLutGreen[(((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                                    | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                                    | (gammaLutBlue[(dstRB & 0x00FF)]));
                                                #endregion
                                                #endregion
                                            }
                                            startXPosition++;
                                        }
                                    }
                                    #endregion
                                }
                                #endregion

                                currentCoverage += currentCellData.Coverage;

                                #region blend the current cell
                                // fast absolute
                                tempCover = ((currentCoverage << 9) - currentArea) >> 9;


                                if (tempCover != 0)
                                {
                                    // fast bit absolute
                                    tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                    //#region non-zero checking code
                                    //if (tempCover > 255) tempCover = 255;
                                    //#endregion
                                    #region even-odd change
                                    tempCover &= 511;
                                    if (tempCover > 256)
                                    {
                                        tempCover = 512 - tempCover;
                                    }
                                    #endregion
                                    // get current color data
                                    #region blend pixel
                                    tempCover = (int)((tempCover * colorAlpha) >> 8);
                                    //if (tempCover > 255) tempCover = 255;
                                    calculatedCoverage = (byte)tempCover;

                                    startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                    #region blend here
                                    //dst = BufferData[startXPosition];
                                    //dstRB = dst & 0x00FF00FF;
                                    //dstG = (dst >> 8) & 0xFF;
                                    //BufferData[startXPosition] =
                                    //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                    //    | (uint)((((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                    //    | (uint)(((((colorRB - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);

                                    #region gamma apply
                                    dst = BufferData[startXPosition];
                                    dstG = (dst >> 8) & 0xFF;
                                    dstRB = ((((colorRB - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                    BufferData[startXPosition] =
                                        (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                        | (((uint)gammaLutGreen[(((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                        | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                        | (gammaLutBlue[(dstRB & 0x00FF)]));
                                    #endregion
                                    #endregion
                                    #endregion
                                }
                                #endregion

                                scLastCoverage = currentCoverage;
                                scLastX = currentCellData.X;

                                // move to next cell
                                currentCellData = currentCellData.Next;
                            } while (currentCellData != null);
                            #endregion
                        }
                    }
                    // increase color index
                    currentColorIndexValue++;
                }
                #endregion
            }
            else
            {
                #region perform normal filling
                startRowIndex--;
                while (++startRowIndex <= endRowIndex)
                {
                    currentCoverage = scLastCoverage = scLastX = 0;

                    if (rows[startRowIndex] != null)
                    {
                        #region calculate and get current color
                        colorData = fixedColor[currentColorIndexValue];
                        colorAlpha = (colorData >> 24);
                        colorG = (colorData & 0x0000FF00) >> 8;
                        colorRB = (colorData & 0x00FF00FF);
                        #endregion
                        // get first cell in current row
                        currentCellData = rows[startRowIndex].First;
                        if (currentCellData != null)
                        {
                            #region fill current row
                            do
                            {
                                currentArea = currentCellData.Area;
                                #region blend horizontal line
                                if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0))
                                {
                                    // fast bit absolute
                                    scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31);
                                    #region even-odd change
                                    scLastCoverage &= 511;
                                    if (scLastCoverage > 256)
                                    {
                                        scLastCoverage = 512 - scLastCoverage;
                                    }
                                    #endregion

                                    #region BLEND HORIZONTAL LINE
                                    // calculate start and end position
                                    startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1;
                                    lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;

                                    while (startXPosition < lastXPosition)
                                    {
                                        calculatedCoverage = (byte)((scLastCoverage * colorAlpha) >> 8);
                                        if (calculatedCoverage >= 254)
                                        {
                                            BufferData[startXPosition] = colorData;
                                        }
                                        else
                                        {
                                            #region blend here
                                            //dst = BufferData[startXPosition];
                                            //dstRB = dst & 0x00FF00FF;
                                            //dstG = (dst >> 8) & 0xFF;

                                            //BufferData[startXPosition] =
                                            //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                            //    | (uint)((((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                            //    | (uint)(((((colorRB - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);

                                            #region gamma apply
                                            dst = BufferData[startXPosition];
                                            dstG = (dst >> 8) & 0xFF;
                                            dstRB = ((((colorRB - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                            BufferData[startXPosition] =
                                                (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                                | (((uint)gammaLutGreen[(((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                                | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                                | (gammaLutBlue[(dstRB & 0x00FF)]));
                                            #endregion
                                            #endregion
                                        }
                                        startXPosition++;
                                    }
                                    #endregion
                                }
                                #endregion

                                currentCoverage += currentCellData.Coverage;

                                #region blend the current cell
                                // fast absolute
                                tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                                if (tempCover != 0)
                                {
                                    // fast bit absolute
                                    tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);

                                    #region even-odd change
                                    tempCover &= 511;
                                    if (tempCover > 256)
                                    {
                                        tempCover = 512 - tempCover;
                                    }
                                    #endregion

                                    #region blend pixel
                                    tempCover = (int)((tempCover * colorAlpha) >> 8);
                                    //if (tempCover > 255) tempCover = 255;
                                    calculatedCoverage = (byte)tempCover;

                                    startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X;
                                    #region blend here
                                    //dst = BufferData[startXPosition];
                                    //dstRB = dst & 0x00FF00FF;
                                    //dstG = (dst >> 8) & 0xFF;
                                    //BufferData[startXPosition] =
                                    //    (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                    //    | (uint)((((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                    //    | (uint)(((((colorRB - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);

                                    #region gamma apply
                                    dst = BufferData[startXPosition];
                                    dstG = (dst >> 8) & 0xFF;
                                    dstRB = ((((colorRB - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF));

                                    BufferData[startXPosition] =
                                        (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage])
                                        | (((uint)gammaLutGreen[(((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                        | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                        | (gammaLutBlue[(dstRB & 0x00FF)]));
                                    #endregion
                                    #endregion
                                    #endregion
                                }
                                #endregion

                                scLastCoverage = currentCoverage;
                                scLastX = currentCellData.X;

                                // move to next cell
                                currentCellData = currentCellData.Next;
                            } while (currentCellData != null);
                            #endregion
                        }
                    }

                    // increase color index
                    currentColorIndexValue++;
                }
                #endregion
            }

            #endregion
        }
		private static List<GradientStop> GetGradientStops(LinearGradient gradient, bool applySmallBlurFocusArea, KernelGenerator kernelGenerator, double firstStopOffset, double lastStopOffset, byte firstKernelIndex = 0)
		{
			var stops = new List<GradientStop>();

			if (kernelGenerator.GetKernelBands().Count > 0)
			{
				double sumOfBandWidths = kernelGenerator.GetKernelBands().Select(band => band.Width).Sum();

				var focusAreaColor = GetFocusAreaColor(applySmallBlurFocusArea);
				stops.Add(new GradientStop() { Color = Color.FromArgb(255, focusAreaColor, focusAreaColor, focusAreaColor), Offset = firstStopOffset });

				var currentStopOffset = lastStopOffset - firstStopOffset > 0
					? firstStopOffset + minDiffBetweenStops
					: firstStopOffset - minDiffBetweenStops;

				var kernelBands = kernelGenerator.GetKernelBands();

				byte kernelIndex = firstKernelIndex;
				foreach (var band in kernelBands)
				{
					kernelIndex++;
					stops.Add(new GradientStop() { Color = Color.FromArgb(255, kernelIndex, kernelIndex, kernelIndex), Offset = currentStopOffset });
					currentStopOffset = currentStopOffset + (band.Width / sumOfBandWidths) * (lastStopOffset - firstStopOffset) * FocusToBlurTransitionWidth;
				}
				stops.Add(new GradientStop() { Color = Color.FromArgb(255, kernelIndex, kernelIndex, kernelIndex), Offset = currentStopOffset });

				stops = EnsureMinDiffBetweenPoints(stops);
			}

			return stops;
		}
		public static IImageProvider Generate(IImageProvider objectMaskSource, LinearGradient gradient, Size size, IReadOnlyList<ILensBlurKernel> kernels)
		{
			var backgroundSource = new GradientImageSource(size, gradient);
            var blendEffect = new BlendEffect(backgroundSource, objectMaskSource, BlendFunction.Lighten);
            return new IndexRemappingEffect(blendEffect, kernels.Count + 2);
		}