/// <summary>
        /// Fill to buffer base rows data information using non-zero rule
        /// </summary>
        /// <param name="paint">paint using for fill</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>
        protected override void OnFillingNonZero(
            PaintMaterial paint,
            RowData[] rows,
            int startRowIndex,
            int endRowIndex)
        {
            if (!(paint.Paint is LinearGradient))
            {
                NotMatchPaintTypeException.Publish(typeof(LinearGradient), paint.Paint.GetType());
                return;
            }
            LinearGradient linearGradient = paint.Paint as LinearGradient;

            switch (linearGradient.Mode)
            {
                case LinearGradientMode.Horizontal:
                    OnFillingHorizontalNonZero(linearGradient, paint.ScaledOpacity, rows, startRowIndex, endRowIndex);
                    break;
                case LinearGradientMode.Vertical:
                    OnFillingVerticalNonZero(linearGradient, paint.ScaledOpacity, rows, startRowIndex, endRowIndex);
                    break;
                case LinearGradientMode.ForwardDiagonal:
                    OnFillingDiagonalNonZero(linearGradient, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, true);
                    break;
                case LinearGradientMode.BackwardDiagonal:
                    OnFillingDiagonalNonZero(linearGradient, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, false);
                    break;
            }
        }
 /// <summary>
 /// Filling row data result from start y index to end y index including transformation
 /// <para>While filling can use CurrentTransformMatrix, or InverterMatrix... to calculate
 /// or access transformation information</para>
 /// </summary>
 /// <param name="paint">paint</param>
 /// <param name="rows">rows</param>
 /// <param name="startYIndex">start y index</param>
 /// <param name="endYIndex">end y index</param>
 protected override void OnFillingTransformedEvenOdd(PaintMaterial paint, RowData[] rows, int startYIndex, int endYIndex)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Fill to buffer base rows data information using even odd rule
 /// </summary>
 /// <param name="paint">paint using for fill</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>
 protected override void OnFillingEvenOdd(PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Filling using radial gradient for circle gradient only
        /// </summary>
        /// <param name="radial">radial</param>
        /// <param name="rows">rows</param>
        /// <param name="startRowIndex">start y index</param>
        /// <param name="endRowIndex">end y index</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 FillingRadialEvenOdd(RadialGradient radial, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue)
        {
            // now not need to check null or not
            uint[] builtColors = radial.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;

            double centerX = radial.CenterX;
            double centerY = radial.CenterY;
            // in this case radius x = radius y
            double radius = radial.RadiusX;

            // saving precompute value for rows
            /* Normal calculation to get the color index
             * currentColorIndexValue =
                (int)(Math.Sqrt(
                    (startRowIndex - centerY) * (startRowIndex - centerY) +
                    (currentXPosition - centerX) * (currentXPosition - centerX)) * ColorIndexScale / radius );
             * but
             *  preComputeForRow= (startRowIndex - centerY) * (startRowIndex - centerY)
             *  so that
             *    currentColorIndexValue = 
             *    (int)(Math.Sqrt(
                    (preComputeForRow) +
                    (currentXPosition - centerX) * (currentXPosition - centerX)) * ColorIndexScale / radius );
             */
            double preComputeForRow = 0;

            // this is precompute value so that (* ColorIndexScale / radius) now just ( * preComputeRadiusLookup )
            double preComputeRadiusLookup = ColorIndexScale / radius;

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


            int currentColorIndexValue = 0;
            int currentXPosition = 0;

            uint dst, dstRB, dstG;
            #endregion

            #region FILLING
            if (radial.Ramp.NoBlendingColor)
            {
                // when no need to blending, when draw a horizontal line
                // do not need check the back color, alway setup
                if (radial.Style != GradientStyle.Pad)
                {
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;
                        preComputeForRow = (startRowIndex - centerY) * (startRowIndex - centerY);
                        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 even odd change
                                        scLastCoverage &= 511;
                                        if (scLastCoverage >= 256)
                                        {
                                            scLastCoverage = 512 - scLastCoverage - 1;
                                        }
                                        #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;
                                            currentXPosition = scLastX + 1;
                                            if (scLastCoverage >= 255)
                                            {
                                                while (startXPosition < lastXPosition)
                                                {
                                                    #region calculate color index
                                                    currentColorIndexValue =
                                                        (int)(Math.Sqrt(
                                                            preComputeForRow +
                                                            (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                                    #endregion
                                                    BufferData[startXPosition] = builtColors[currentColorIndexValue & ColorIndexDoubleMask];
                                                    startXPosition++;
                                                    currentXPosition++;
                                                }
                                            }
                                            else
                                            {
                                                calculatedCoverage = (byte)scLastCoverage;
                                                while (startXPosition < lastXPosition)
                                                {
                                                    #region calculate color index
                                                    currentColorIndexValue =
                                                        (int)(Math.Sqrt(
                                                            preComputeForRow +
                                                            (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                                    #endregion

                                                    colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];
                                                    //calculatedCoverage = (byte)((colorData >> 24));
                                                    //calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);
                                                    if (calculatedCoverage >= 254)
                                                    {
                                                        BufferData[startXPosition] = colorData;
                                                    }
                                                    else
                                                    {
                                                        #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 & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                                            | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                                            | (gammaLutBlue[(dstRB & 0x00FF)]))
                                                            ;
                                                        #endregion
                                                    }
                                                    startXPosition++;
                                                    currentXPosition++;
                                                }
                                            }
                                            #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 - 1;
                                        }
                                        #endregion
                                        // get current color data
                                        #region calculate color index
                                        currentXPosition = currentCellData.X;
                                        currentColorIndexValue =
                                            (int)(Math.Sqrt(preComputeForRow +
                                                (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                        #endregion

                                        colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];//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);
                                        if (calculatedCoverage >= 254)
                                        {
                                            BufferData[startXPosition] = colorData;
                                        }
                                        else
                                        {
                                            #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 & 0x00FF00) >> 8) - 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
                            }
                        }
                    }
                    #endregion
                }
                else
                {
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;
                        preComputeForRow = (startRowIndex - centerY) * (startRowIndex - centerY);
                        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 even odd change
                                        scLastCoverage &= 511;
                                        if (scLastCoverage >= 256)
                                        {
                                            scLastCoverage = 512 - scLastCoverage - 1;
                                        }
                                        #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;
                                            currentXPosition = scLastX + 1;
                                            if (scLastCoverage >= 255)
                                            {
                                                while (startXPosition < lastXPosition)
                                                {
                                                    #region calculate color index
                                                    currentColorIndexValue =
                                                        (int)(Math.Sqrt(
                                                            preComputeForRow +
                                                            (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                                    #endregion
                                                    BufferData[startXPosition] = builtColors[currentColorIndexValue > 254 ? 255 : currentColorIndexValue];
                                                    startXPosition++;
                                                    currentXPosition++;
                                                }
                                            }
                                            else
                                            {
                                                calculatedCoverage = (byte)(scLastCoverage);
                                                while (startXPosition < lastXPosition)
                                                {
                                                    #region calculate color index
                                                    currentColorIndexValue =
                                                        (int)(Math.Sqrt(
                                                            preComputeForRow +
                                                            (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                                    #endregion

                                                    colorData = builtColors[currentColorIndexValue > 254 ? 255 : currentColorIndexValue];
                                                    //calculatedCoverage = (byte)((colorData >> 24));
                                                    //calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);
                                                    if (calculatedCoverage >= 254)
                                                    {
                                                        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 & 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 & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                                            | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                                            | (gammaLutBlue[(dstRB & 0x00FF)]))
                                                            ;
                                                        #endregion
                                                    }
                                                    startXPosition++;
                                                    currentXPosition++;
                                                }
                                            }
                                            #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 - 1;
                                        }
                                        #endregion
                                        // get current color data
                                        #region calculate color index
                                        currentXPosition = currentCellData.X;
                                        currentColorIndexValue =
                                            (int)(Math.Sqrt(preComputeForRow +
                                                (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                        #endregion

                                        colorData = builtColors[currentColorIndexValue > 254 ? 255 : currentColorIndexValue];//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);
                                        if (calculatedCoverage >= 254)
                                        {
                                            BufferData[startXPosition] = colorData;
                                        }
                                        else
                                        {
                                            #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 & 0x00FF00) >> 8) - 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
                            }
                        }
                    }
                    #endregion
                }
            }
            else
            {
                // when no need to blending, when draw a horizontal line
                // do not need check the back color, alway setup
                if (radial.Style != GradientStyle.Pad)
                {
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;
                        preComputeForRow = (startRowIndex - centerY) * (startRowIndex - centerY);
                        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 even odd change
                                        scLastCoverage &= 511;
                                        if (scLastCoverage >= 256)
                                        {
                                            scLastCoverage = 512 - scLastCoverage - 1;
                                        }
                                        #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;
                                            currentXPosition = scLastX + 1;

                                            while (startXPosition < lastXPosition)
                                            {
                                                #region calculate color index
                                                currentColorIndexValue =
                                                    (int)(Math.Sqrt(
                                                        preComputeForRow +
                                                        (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                                #endregion

                                                colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];
                                                calculatedCoverage = (byte)((colorData >> 24));
                                                calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);
                                                if (calculatedCoverage >= 254)
                                                {
                                                    BufferData[startXPosition] = colorData;
                                                }
                                                else
                                                {
                                                    #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 & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                                        | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                                        | (gammaLutBlue[(dstRB & 0x00FF)]))
                                                        ;
                                                    #endregion
                                                }
                                                startXPosition++;
                                                currentXPosition++;
                                            }
                                            #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 - 1;
                                        }
                                        #endregion
                                        // get current color data
                                        #region calculate color index
                                        currentXPosition = currentCellData.X;
                                        currentColorIndexValue =
                                            (int)(Math.Sqrt(preComputeForRow +
                                                (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                        #endregion

                                        colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];//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);
                                        #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 & 0x00FF00) >> 8) - 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
                            }
                        }
                    }
                    #endregion
                }
                else
                {
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;
                        preComputeForRow = (startRowIndex - centerY) * (startRowIndex - centerY);
                        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 even odd change
                                        scLastCoverage &= 511;
                                        if (scLastCoverage >= 256)
                                        {
                                            scLastCoverage = 512 - scLastCoverage - 1;
                                        }
                                        #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;
                                            currentXPosition = scLastX + 1;

                                            while (startXPosition < lastXPosition)
                                            {
                                                #region calculate color index
                                                currentColorIndexValue =
                                                    (int)(Math.Sqrt(
                                                        preComputeForRow +
                                                        (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                                #endregion

                                                colorData = builtColors[currentColorIndexValue > 254 ? 255 : currentColorIndexValue];
                                                calculatedCoverage = (byte)((colorData >> 24));
                                                calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);
                                                if (calculatedCoverage >= 254)
                                                {
                                                    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 & 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 & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8))
                                                        | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16)
                                                        | (gammaLutBlue[(dstRB & 0x00FF)]))
                                                        ;
                                                    #endregion
                                                }
                                                startXPosition++;
                                                currentXPosition++;
                                            }
                                            #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 - 1;
                                        }
                                        #endregion
                                        // get current color data
                                        #region calculate color index
                                        currentXPosition = currentCellData.X;
                                        currentColorIndexValue =
                                            (int)(Math.Sqrt(preComputeForRow +
                                                (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                        #endregion

                                        colorData = builtColors[currentColorIndexValue > 254 ? 255 : currentColorIndexValue];//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);
                                        #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 & 0x00FF00) >> 8) - 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
                            }
                        }
                    }
                    #endregion
                }
            }

            #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
        }
 /// <summary>
 /// Fill to buffer base rows data information using even odd rule
 /// </summary>
 /// <param name="paint">paint using for fill</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>
 protected abstract void OnFillingEvenOdd(PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex);
 /// <summary>
 /// Filling method including prepare material and perform filling
 /// </summary>
 /// <param name="paint">paint</param>
 /// <param name="rows">rows</param>
 /// <param name="startYIndex">start y index</param>
 /// <param name="endYIndex">end y index</param>
 protected void Filling(PaintMaterial paint, RowData[] rows, int startYIndex, int endYIndex)
 {
     //this.CurrentPaint = paint;
     PrepareMaterial(paint, CurrentStartXIndex, startYIndex, CurrentEndXIndex, endYIndex);
     OnFilling(paint, rows, startYIndex, endYIndex);
     OnFinishFilling();
 }
        /// <summary>
        /// Rasterize and fill the polygon directly in one pass. This approach is slightly faster than the normal renderation process (Begin, Addxxx, Finish)
        /// </summary>
        /// <param name="paint">The paint material used for filling</param>
        /// <param name="data">raw data array in format [x1,y1, x2,y2, ...]</param>
        /// <param name="pointCount">Number of points contained within data</param>
        /// <param name="startOffset">Index of the first point in data </param>
        /// <param name="offsetX">offseted X</param>
        /// <param name="offsetY">offseted Y</param>
        public void FillPolygon(PaintMaterial paint, double[] data, int pointCount, int startOffset, double offsetX, double offsetY)
        {
            if (IsClipBoxOutSideBound)
            {
                return;
            }
            double calculatedX = 0, calculatedY = 0;

            int endIndex = startOffset + pointCount * 2;
            #region determine the startY,endY
            // Start,end y for drawing
            int endRowPosition = int.MinValue;
            int startRowPosition = int.MaxValue;
            CurrentStartXIndex = int.MaxValue;
            CurrentEndXIndex = int.MinValue;
            for (int i = startOffset; i < endIndex; i += 2)
            {
                calculatedX = data[i] + offsetX;
                calculatedY = data[i + 1] + offsetY;
                if (calculatedX > CurrentEndXIndex)
                {
                    CurrentEndXIndex = (int)calculatedX + 1;
                }
                if (calculatedX < CurrentStartXIndex)
                {
                    CurrentStartXIndex = (int)calculatedX;
                }
                if (calculatedY > endRowPosition)
                {
                    endRowPosition = (int)calculatedY + 1;
                }
                if (calculatedY < startRowPosition)
                {
                    startRowPosition = (int)calculatedY;
                }
            }
            #endregion
            #region prepare Rows array
            startRowPosition--;
            endRowPosition++;

            if (startRowPosition < ClippingBoxYMin)
            {
                startRowPosition = (int)ClippingBoxYMin;
            }
            if (endRowPosition > ClippingBoxYMax + 1)
            {
                endRowPosition = (int)ClippingBoxYMax + 1;
            }

            for (int rowIndex = startRowPosition; rowIndex <= endRowPosition; rowIndex++)
            {
                Rows[rowIndex] = new RowData();
            }
            #endregion
            #region draw lines

            CurrentXPosition = data[startOffset] + offsetX;
            CurrentYPosition = data[startOffset + 1] + offsetY;
            CurrentPositionFlag =
               ((CurrentXPosition > ClippingBoxXMax) ? XMaxClippingFlag :
               (CurrentXPosition < ClippingBoxXMin) ? XMinClippingFlag : 0)
               |
               ((CurrentYPosition > ClippingBoxYMax) ? YMaxClippingFlag :
               (CurrentYPosition < ClippingBoxYMin) ? YMinClippingFlag : 0);

            for (int i = startOffset + 2; i < endIndex; i += 2)
            {
                if (CurrentYPosition != data[i + 1] + offsetY)
                {
                    DrawAndClippedLine(data[i] + offsetX, data[i + 1] + offsetY);
                }
                else
                {
                    // just move to and calculate the flag
                    CurrentXPosition = data[i] + offsetX;
                    CurrentYPosition = data[i + 1] + offsetY;
                    CurrentPositionFlag =
                      ((CurrentXPosition > ClippingBoxXMax) ? XMaxClippingFlag :
                      (CurrentXPosition < ClippingBoxXMin) ? XMinClippingFlag : 0)
                      |
                      ((CurrentYPosition > ClippingBoxYMax) ? YMaxClippingFlag :
                      (CurrentYPosition < ClippingBoxYMin) ? YMinClippingFlag : 0);
                }
            }

            if (CurrentYPosition != data[startOffset + 1] + offsetY)
            {
                DrawAndClippedLine(data[startOffset] + offsetX, data[startOffset + 1] + offsetY);
            }

            #endregion
            #region fill
            Filling(paint, Rows, startRowPosition, endRowPosition);

            #endregion

        }
        /// <summary>
        /// Fill to buffer base rows data information using non zero rule
        /// </summary>
        /// <param name="paint">paint using for fill</param>
        /// <param name="rows">row data information</param>
        /// <param name="startYIndex">start row index in row array need to draw</param>
        /// <param name="endYIndex">end row index in end row array need to draw</param>
        protected void OnBuildingNonZero(RowData[] rows, int startYIndex, int endYIndex)
        {
            #region private variable for filling
            int currentCoverage, scLastCoverage, scLastX = 0;
            int tempCover = 0;
            int currentArea = 0;
            int lastXPosition = 0;
            int startXPosition = 0;
            CellData currentCellData = null;
            byte calculatedCoverage = 0;

            byte[] MaskData = mResultMask.Data;

            int maskStartOffset = mResultMask.StartOffset;
            int maskStride = mResultMask.Stride;
            #endregion
            startYIndex--;
            while (++startYIndex <= endYIndex)
            {
                currentCoverage = scLastCoverage = scLastX = 0;

                if (rows[startYIndex] != null)
                {
                    // get first cell in current row
                    currentCellData = rows[startYIndex].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 this check for non zero case
                                if (scLastCoverage > 255) scLastCoverage = 255;
                                #endregion
                                //fill from currentX position to last x position
                                //scLastCoverage = (byte)((scLastCoverage * colorAlpha) >> 8);

                                #region BLEND HORIZONTAL LINE
                                // calculate start and end position
                                startXPosition = maskStartOffset + startYIndex * maskStride + scLastX + 1;
                                lastXPosition = maskStartOffset + startYIndex * maskStride + currentCellData.X;
                                calculatedCoverage = (byte)scLastCoverage;
                                while (startXPosition < lastXPosition)
                                {
                                    MaskData[startXPosition++] = calculatedCoverage;
                                }
                                #endregion
                            }
                            #endregion

                            currentCoverage += currentCellData.Coverage;

                            #region blend the current cell
                            // calculate tempcover
                            tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                            if (tempCover != 0)
                            {
                                // fast bit absolute
                                tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);
                                #region this check using for non zero
                                if (tempCover > 255) tempCover = 255;
                                #endregion

                                startXPosition = maskStartOffset + startYIndex * maskStride + currentCellData.X;
                                MaskData[startXPosition] = (byte)tempCover;
                            }
                            #endregion

                            scLastCoverage = currentCoverage;
                            scLastX = currentCellData.X;

                            // move to next cell
                            currentCellData = currentCellData.Next;
                        } while (currentCellData != null);
                        #endregion
                    }
                }
            }
        }
 /// <summary>
 /// Build mask base on rows result of rasterizer
 /// </summary>
 /// <param name="rows">rasterized result</param>
 /// <param name="startRowPosition">start row</param>
 /// <param name="endRowPosition">end row</param>
 protected void BuildMask(RowData[] rows, int startRowPosition, int endRowPosition)
 {
     if (mFillingRule == FillingRule.NonZero)
     {
         OnBuildingNonZero(rows, startRowPosition, endRowPosition);
     }
     else
     {
         OnBuildingEvenOdd(rows, startRowPosition, endRowPosition);
     }
 }
 /// <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>
        /// Filling row data result from start y index to end y index including transformation
        /// <para>While filling can use CurrentTransformMatrix, or InverterMatrix... to calculate
        /// or access transformation information</para>
        /// </summary>
        /// <param name="paint">paint</param>
        /// <param name="rows">rows</param>
        /// <param name="startYIndex">start y index</param>
        /// <param name="endYIndex">end y index</param>
        protected override void OnFillingTransformedNonZero(
            PaintMaterial paint,
            RowData[] rows,
            int startYIndex,
            int endYIndex)
        {
            if (!(paint.Paint is LinearGradient))
            {
                //throw new NotImplementedException("Support color paint only");
                NotMatchPaintTypeException.Publish(typeof(LinearGradient), paint.Paint.GetType());
                return;
            }
            LinearGradient linearGradient = paint.Paint as LinearGradient;

            switch (linearGradient.Mode)
            {
                case LinearGradientMode.Horizontal:
                    OnFillingTransformedHorizontalNonZero(linearGradient, paint.ScaledOpacity, rows, startYIndex, endYIndex);
                    break;
                case LinearGradientMode.Vertical:
                    OnFillingTransformedVerticalNonZero(linearGradient, paint.ScaledOpacity, rows, startYIndex, endYIndex);
                    break;
                case LinearGradientMode.ForwardDiagonal:
                    OnFillingTransformedDiagonalNonZero(linearGradient, paint.ScaledOpacity, rows, startYIndex, endYIndex, true);
                    break;
                case LinearGradientMode.BackwardDiagonal:
                    OnFillingTransformedDiagonalNonZero(linearGradient, paint.ScaledOpacity, rows, startYIndex, endYIndex, false);
                    break;
            }
        }
 /// <summary>
 /// Filling row data result from start y index to end y index including transformation
 /// <para>While filling can use CurrentTransformMatrix, or InverterMatrix... to calculate
 /// or access transformation information</para>
 /// </summary>
 /// <param name="paint">paint</param>
 /// <param name="rows">rows</param>
 /// <param name="startYIndex">start y index</param>
 /// <param name="endYIndex">end y index</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>
 protected override void OnFillingTransformedNonZero(PaintMaterial paint, RowData[] rows, int startYIndex, int endYIndex, 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">paint using for fill</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>
 protected override void OnFillingNonZero(PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Fill to buffer base rows data information using EvenOdd rule
        /// </summary>
        /// <param name="paint">paint using for fill</param>
        /// <param name="rows">row data information</param>
        /// <param name="startYIndex">start row index in row array need to draw</param>
        /// <param name="endYIndex">end row index in end row array need to draw</param>
        protected void OnBuildingEvenOdd(RowData[] rows, int startYIndex, int endYIndex)
        {

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

            byte[] MaskData = mResultMask.Data;

            int maskStartOffset = mResultMask.StartOffset;
            int maskStride = mResultMask.Stride;
            #endregion

            startYIndex--;
            while (++startYIndex <= endYIndex)
            {
                currentCoverage = scLastCoverage = scLastX = 0;

                if (rows[startYIndex] != null)
                {
                    // get first cell in current row
                    currentCellData = rows[startYIndex].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;
                                //}

                                scLastCoverage &= 511;
                                if (scLastCoverage >= 256)
                                {
                                    scLastCoverage = 512 - scLastCoverage - 1;
                                }
                                #endregion

                                if (scLastCoverage != 0)
                                {
                                    #region BLEND HORIZONTAL LINE
                                    // calculate start and end position
                                    startXPosition = maskStartOffset + startYIndex * maskStride + scLastX + 1;
                                    lastXPosition = maskStartOffset + startYIndex * maskStride + currentCellData.X;
                                    calculatedCoverage = (byte)scLastCoverage;
                                    while (startXPosition < lastXPosition)
                                    {
                                        MaskData[startXPosition++] = calculatedCoverage;
                                    }
                                    #endregion
                                }
                            }
                            #endregion

                            currentCoverage += currentCellData.Coverage;

                            #region blend the current cell
                            // fast absolute
                            tempCover = ((currentCoverage << 9) - currentArea) >> 9;
                            // fast bit absolute
                            tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31);
                            //tempCover &= 511;
                            //if (tempCover >= 256)
                            //{
                            //    tempCover = 512 - tempCover;
                            //}

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

                            if (tempCover != 0)
                            {
                                startXPosition = maskStartOffset + startYIndex * maskStride + currentCellData.X;
                                MaskData[startXPosition] = (byte)tempCover;
                            }
                            #endregion

                            scLastCoverage = currentCoverage;
                            scLastX = currentCellData.X;

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

        #region PrepareBuffer
        /// <summary>
        /// Preparing buffer and internal data for using
        /// </summary>
        /// <param name="buffer">buffer</param>
        protected virtual void PrepareBuffer(PixelsBuffer buffer)
        {
            //automatically create a new boundary to match this buffer
            if (mBuffer == null)
            {
                //mBoundary = Boundary.Empty;
                DestBufferWidth = 0;
                DestBufferHeight = 0;
                BufferStride = 0;
                BufferStartOffset = 0;
                BufferData = null;
            }
            else
            {
                //mBoundary = new Boundary(mBuffer.Width, mBuffer.Height);
                DestBufferWidth = mBuffer.Width;
                DestBufferHeight = mBuffer.Height;
                BufferStride = mBuffer.Stride;
                BufferStartOffset = mBuffer.StartOffset;
                BufferData = mBuffer.Data;
                //mPixelRenderer.PixelBuffer = mBuffer;
            }
            if ((Rows == null) || (Rows.Length < DestBufferHeight + 1))
            {
                Rows = new RowData[DestBufferHeight + 1];
            }
            SetClip(0, 0, DestBufferWidth, DestBufferHeight);

        }
        /// <summary>
        /// Rasterize and fill the polygon directly in one pass. This approach is slightly faster than the normal renderation process (Begin, Addxxx, Finish)
        /// </summary>
        /// <param name="paint">The paint material used for filling</param>
        /// <param name="data">raw data array in format [x1,y1, x2,y2, ...]</param>
        /// <param name="pointCount">Number of points contained within data</param>
        /// <param name="startOffset">Index of the first point in data </param>
        /// <param name="offsetX">offseted X</param>
        /// <param name="offsetY">offseted Y</param>
        public void FillPolygon(PaintMaterial paint, double[] data, int pointCount, int startOffset, double offsetX, double offsetY)
        {
            if (IsClipBoxOutSideBound)
            {
                return;
            }
            double calculatedX = 0, calculatedY = 0;

            int endIndex = startOffset + pointCount * 2;

            #region determine the startY,endY
            // Start,end y for drawing
            int endRowPosition   = int.MinValue;
            int startRowPosition = int.MaxValue;
            CurrentStartXIndex = int.MaxValue;
            CurrentEndXIndex   = int.MinValue;
            for (int i = startOffset; i < endIndex; i += 2)
            {
                calculatedX = data[i] + offsetX;
                calculatedY = data[i + 1] + offsetY;
                if (calculatedX > CurrentEndXIndex)
                {
                    CurrentEndXIndex = (int)calculatedX + 1;
                }
                if (calculatedX < CurrentStartXIndex)
                {
                    CurrentStartXIndex = (int)calculatedX;
                }
                if (calculatedY > endRowPosition)
                {
                    endRowPosition = (int)calculatedY + 1;
                }
                if (calculatedY < startRowPosition)
                {
                    startRowPosition = (int)calculatedY;
                }
            }
            #endregion
            #region prepare Rows array
            startRowPosition--;
            endRowPosition++;

            if (startRowPosition < ClippingBoxYMin)
            {
                startRowPosition = (int)ClippingBoxYMin;
            }
            if (endRowPosition > ClippingBoxYMax + 1)
            {
                endRowPosition = (int)ClippingBoxYMax + 1;
            }

            for (int rowIndex = startRowPosition; rowIndex <= endRowPosition; rowIndex++)
            {
                Rows[rowIndex] = new RowData();
            }
            #endregion
            #region draw lines

            CurrentXPosition    = data[startOffset] + offsetX;
            CurrentYPosition    = data[startOffset + 1] + offsetY;
            CurrentPositionFlag =
                ((CurrentXPosition > ClippingBoxXMax) ? XMaxClippingFlag :
                 (CurrentXPosition < ClippingBoxXMin) ? XMinClippingFlag : 0)
                |
                ((CurrentYPosition > ClippingBoxYMax) ? YMaxClippingFlag :
                 (CurrentYPosition < ClippingBoxYMin) ? YMinClippingFlag : 0);

            for (int i = startOffset + 2; i < endIndex; i += 2)
            {
                if (CurrentYPosition != data[i + 1] + offsetY)
                {
                    DrawAndClippedLine(data[i] + offsetX, data[i + 1] + offsetY);
                }
                else
                {
                    // just move to and calculate the flag
                    CurrentXPosition    = data[i] + offsetX;
                    CurrentYPosition    = data[i + 1] + offsetY;
                    CurrentPositionFlag =
                        ((CurrentXPosition > ClippingBoxXMax) ? XMaxClippingFlag :
                         (CurrentXPosition < ClippingBoxXMin) ? XMinClippingFlag : 0)
                        |
                        ((CurrentYPosition > ClippingBoxYMax) ? YMaxClippingFlag :
                         (CurrentYPosition < ClippingBoxYMin) ? YMinClippingFlag : 0);
                }
            }

            if (CurrentYPosition != data[startOffset + 1] + offsetY)
            {
                DrawAndClippedLine(data[startOffset] + offsetX, data[startOffset + 1] + offsetY);
            }

            #endregion
            #region fill
            BuildMask(Rows, startRowPosition, endRowPosition);
            //Filling(paint, Rows, startRowPosition, endRowPosition);

            #endregion
        }
 /// <summary>
 /// Perform filling into rasterized result 
 /// </summary>
 /// <param name="paint">paint</param>
 /// <param name="rows">rows</param>
 /// <param name="startYIndex">start y index</param>
 /// <param name="endYIndex">end y index</param>
 protected virtual void OnFilling(PaintMaterial paint, RowData[] rows, int startYIndex, int endYIndex)
 {
     //outside of box, no need to fill
     if (IsClipBoxOutSideBound) return;
     //Cross.Log.Debug("Start row {0}, end rows {1}",startYIndex,endYIndex);
     // when gamma function is assigned and gamma function need to apply
     //if ((mGamma != null) &&(mGamma.IsAppliedGamma))
     if ((mGamma != null))
     {
         if (paint.FillingRule == FillingRule.NonZero)
         {
             // fill non-zero including gamma
             OnFillingNonZero(paint, Rows, startYIndex, endYIndex, mGamma.GetLookupTableRed(), mGamma.GetLookupTableGreen(), mGamma.GetLookupTableBlue());
         }
         else
         {
             // fill Even-Odd including gamma
             OnFillingEvenOdd(paint, Rows, startYIndex, endYIndex, mGamma.GetLookupTableRed(), mGamma.GetLookupTableGreen(), mGamma.GetLookupTableBlue());
         }
     }
     else
     {
         //Cross.Log.Debug("Filling without gamma");
         if (paint.FillingRule == FillingRule.NonZero)
         {
             OnFillingNonZero(paint, Rows, startYIndex, endYIndex);
         }
         else
         {
             OnFillingEvenOdd(paint, Rows, startYIndex, endYIndex);
         }
     }
 }
        /// <summary>
        /// Filling using radial gradient for circle gradient only
        /// </summary>
        /// <param name="radial">radial</param>
        /// <param name="rows">rows</param>
        /// <param name="startRowIndex">start y index</param>
        /// <param name="endRowIndex">end y index</param>
        void FillingEllipseFocalEvenOdd(RadialGradient radial, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex)
        {
            // now not need to check null or not
            uint[] builtColors = radial.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;


            double centerX = radial.CenterX;
            double centerY = radial.CenterY;
            // in this case radius x = radius y
            double radius = radial.RadiusX;
            double radiusYForX = radial.RadiusY / radial.RadiusX;


            // this is precompute value so that (* ColorIndexScale / radius) now just ( * preComputeRadiusLookup )
            double preComputeRadiusLookup = ColorIndexScale / radius;

            CellData currentCellData = null;
            uint colorData = 0;

            double dx = 0, dy = 0;

            double dySquared = 0; // saving dy * dy
            // focus is changed to relative from the center
            double absoluteFocusX = radial.FocusX;
            double absoluteFocusY = radial.FocusY;

            double focusX = radial.FocusX - centerX;
            double focusY = radial.FocusY - centerY;
            focusY = focusY / radiusYForX;

            // note that dx,dy need to move center
            /*
             *  dx = (currentXPosition - absoluteFocusX);
             *  dy = (startRowIndex - absoluteFocusY);
             *  currentColorIndexValue =
                    (int)
                    (
                        (
                            (
                            (dx * focusX) + (dy * focusY)
                            + Math.Sqrt
                            (
                                Math.Abs
                                (
                                    radius * radius * (dx * dx + dy * dy) - (dx * focusY - dy * focusX) * (dx * focusY - dy * focusX)      
                                )
                            )
                        ) * (radius /
                        ((radius * radius) - ((focusX * focusX )+ (focusY * focusY))))
                    ) * 256 /radius
                );
             */

            //note that  ( radius / (( radius * radius) - ((focusX * focusX) + (focusY * focusY))) is const
            // so that need to pre compute
            double preComputeMultiply = radius / ((radius * radius) - ((focusX * focusX) + (focusY * focusY)));

            #region modify when pre compute for multiply is zero
            if (preComputeMultiply == 0)
            {
                if (focusX != 0)
                {
                    if (focusX < 0)
                    {
                        focusX += GradientAdjustment;
                    }
                    else
                    {
                        focusX -= GradientAdjustment;
                    }
                }
                if (focusY != 0)
                {
                    if (focusY < 0)
                    {
                        focusY += GradientAdjustment;
                    }
                    else
                    {
                        focusY -= GradientAdjustment;
                    }
                }
                preComputeMultiply = radius / ((radius * radius) - ((focusX * focusX) + (focusY * focusY)));
            }
            #endregion

            double preComputeMultiplyIncludeLookup = preComputeRadiusLookup * preComputeMultiply;

            // saving dy * focusY
            double dyFocusY = 0;
            double dyFocusX = 0;
            double dxFocusYIncrement = 0; // saving dx * focusY - dyFocusX
            double radiusSquared = radius * radius;


            int currentColorIndexValue = 0;
            //int currentXPosition = 0;
            uint dst, dstRB, dstG;
            #endregion

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

                        #region cumpute value for row
                        //dyFocusY = (startRowIndex - centerY) * (startRowIndex - centerY);
                        dy = ((startRowIndex - centerY) / radiusYForX) - focusY;
                        dySquared = dy * dy;
                        dyFocusX = dy * focusX;
                        dyFocusY = dy * focusY;
                        #endregion
                        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 even odd change
                                        scLastCoverage &= 511;
                                        if (scLastCoverage >= 256)
                                        {
                                            scLastCoverage = 512 - scLastCoverage - 1;
                                        }
                                        #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;

                                            #region prepare for row color index calculation
                                            // get current color index value
                                            //currentColorIndexValue = scLastX + 1 - CurrentStartXIndex;
                                            //currentXPosition = scLastX + 1;
                                            dx = (scLastX + 1 - absoluteFocusX);
                                            dxFocusYIncrement = (dx * focusY - dyFocusX);
                                            #endregion
                                            if (scLastCoverage >= 255)
                                            {
                                                while (startXPosition < lastXPosition)
                                                {
                                                    #region calculate color index
                                                    currentColorIndexValue =
                                                        (int)
                                                        ((((dx * focusX) + dyFocusY +
                                                            Math.Sqrt(Math.Abs(
                                                                radiusSquared *
                                                                (dx * dx + dySquared) -
                                                                dxFocusYIncrement * dxFocusYIncrement))
                                                                ) * preComputeMultiplyIncludeLookup)
                                                        );

                                                    //currentColorIndexValue =
                                                    //    (int)
                                                    //    (
                                                    //        (
                                                    //            (
                                                    //            (dx * focusX) + (dy * focusY)
                                                    //            + Math.Sqrt
                                                    //            (
                                                    //                Math.Abs
                                                    //                (
                                                    //                    radius * radius 
                                                    //                    * (dx * dx + dy * dy) 
                                                    //                    - (dx * focusY - dy * focusX) 
                                                    //                    * (dx * focusY - dy * focusX)
                                                    //                )
                                                    //            )
                                                    //        ) * (radius /
                                                    //        ((radius * radius) - ((focusX * focusX) + (focusY * focusY))))
                                                    //        ) * 256 / radius
                                                    //    );

                                                    // change for color index calculation
                                                    dx++;
                                                    dxFocusYIncrement += focusY;
                                                    #endregion
                                                    BufferData[startXPosition] = builtColors[currentColorIndexValue & ColorIndexDoubleMask];
                                                    startXPosition++;
                                                }
                                            }
                                            else
                                            {
                                                calculatedCoverage = (byte)scLastCoverage;
                                                while (startXPosition < lastXPosition)
                                                {

                                                    #region calculate color index
                                                    currentColorIndexValue =
                                                        (int)
                                                        ((((dx * focusX) + dyFocusY +
                                                            Math.Sqrt(Math.Abs(
                                                                radiusSquared *
                                                                (dx * dx + dySquared) -
                                                                dxFocusYIncrement * dxFocusYIncrement))
                                                                ) * preComputeMultiplyIncludeLookup)
                                                        );

                                                    // change for color index calculation
                                                    dx++;
                                                    dxFocusYIncrement += focusY;
                                                    #endregion

                                                    colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];
                                                    //calculatedCoverage = (byte)((colorData >> 24));
                                                    //calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);
                                                    if (calculatedCoverage >= 254)
                                                    {
                                                        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 & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                            | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                    }
                                                    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 - 1;
                                        }
                                        #endregion
                                        // get current color data
                                        #region calculate color index
                                        //currentXPosition = currentCellData.X;
                                        //currentColorIndexValue =
                                        //    (int)(Math.Sqrt(dyFocusY +
                                        //        (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup);
                                        #region prepare for row color index calculation
                                        // get current color index value
                                        dx = (currentCellData.X - absoluteFocusX);
                                        dxFocusYIncrement = (dx * focusY - dyFocusX);
                                        #endregion

                                        #region calculate color index
                                        currentColorIndexValue =
                                            (int)
                                            ((((dx * focusX) + dyFocusY +
                                                Math.Sqrt(Math.Abs(
                                                    radiusSquared *
                                                    (dx * dx + dySquared) -
                                                    dxFocusYIncrement * dxFocusYIncrement))
                                                    ) * preComputeMultiplyIncludeLookup)
                                            );
                                        #endregion
                                        #endregion

                                        colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];//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
                }
                else
                {
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;
                        #region cumpute value for row
                        //dyFocusY = (startRowIndex - centerY) * (startRowIndex - centerY);
                        dy = ((startRowIndex - centerY) / radiusYForX) - focusY;
                        dySquared = dy * dy;
                        dyFocusX = dy * focusX;
                        dyFocusY = dy * focusY;
                        #endregion
                        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 even odd change
                                        scLastCoverage &= 511;
                                        if (scLastCoverage >= 256)
                                        {
                                            scLastCoverage = 512 - scLastCoverage - 1;
                                        }
                                        #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;
                                            #region prepare for row color index calculation
                                            // get current color index value
                                            dx = (scLastX + 1 - absoluteFocusX);
                                            dxFocusYIncrement = (dx * focusY - dyFocusX);
                                            #endregion

                                            if (scLastCoverage >= 255)
                                            {
                                                while (startXPosition < lastXPosition)
                                                {
                                                    #region calculate color index
                                                    currentColorIndexValue =
                                                        (int)
                                                        ((((dx * focusX) + dyFocusY +
                                                            Math.Sqrt(Math.Abs(
                                                                radiusSquared *
                                                                (dx * dx + dySquared) -
                                                                dxFocusYIncrement * dxFocusYIncrement))
                                                                ) * preComputeMultiplyIncludeLookup)
                                                        );

                                                    // change for color index calculation
                                                    dx++;
                                                    dxFocusYIncrement += focusY;
                                                    #endregion

                                                    BufferData[startXPosition] = builtColors[currentColorIndexValue < 0 ? 0 : currentColorIndexValue > 254 ? 255 : currentColorIndexValue];
                                                    startXPosition++;
                                                }
                                            }
                                            else
                                            {
                                                calculatedCoverage = (byte)(scLastCoverage);
                                                while (startXPosition < lastXPosition)
                                                {
                                                    #region calculate color index
                                                    currentColorIndexValue =
                                                        (int)
                                                        ((((dx * focusX) + dyFocusY +
                                                            Math.Sqrt(Math.Abs(
                                                                radiusSquared *
                                                                (dx * dx + dySquared) -
                                                                dxFocusYIncrement * dxFocusYIncrement))
                                                                ) * preComputeMultiplyIncludeLookup)
                                                        );

                                                    // change for color index calculation
                                                    dx++;
                                                    dxFocusYIncrement += focusY;
                                                    #endregion
                                                    colorData = builtColors[currentColorIndexValue < 0 ? 0 : currentColorIndexValue > 254 ? 255 : currentColorIndexValue];
                                                    //calculatedCoverage = (byte)((colorData >> 24));
                                                    //calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);
                                                    if (calculatedCoverage >= 254)
                                                    {
                                                        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 & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                            | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                    }
                                                    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 - 1;
                                        }
                                        #endregion
                                        // get current color data
                                        #region calculate color index
                                        #region prepare for row color index calculation
                                        // get current color index value
                                        dx = (currentCellData.X - absoluteFocusX);
                                        dxFocusYIncrement = (dx * focusY - dyFocusX);
                                        #endregion

                                        #region calculate color index
                                        currentColorIndexValue =
                                            (int)
                                            ((((dx * focusX) + dyFocusY +
                                                Math.Sqrt(Math.Abs(
                                                    radiusSquared *
                                                    (dx * dx + dySquared) -
                                                    dxFocusYIncrement * dxFocusYIncrement))
                                                    ) * preComputeMultiplyIncludeLookup)
                                            );
                                        #endregion
                                        #endregion

                                        colorData = builtColors[currentColorIndexValue < 0 ? 0 : currentColorIndexValue > 254 ? 255 : currentColorIndexValue];
                                        //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
                }
            }
            else
            {
                // when no need to blending, when draw a horizontal line
                // do not need check the back color, alway setup
                if (radial.Style != GradientStyle.Pad)
                {
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;
                        #region cumpute value for row
                        //dyFocusY = (startRowIndex - centerY) * (startRowIndex - centerY);
                        dy = ((startRowIndex - centerY) / radiusYForX) - focusY;
                        dySquared = dy * dy;
                        dyFocusX = dy * focusX;
                        dyFocusY = dy * focusY;
                        #endregion
                        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 even odd change
                                        scLastCoverage &= 511;
                                        if (scLastCoverage >= 256)
                                        {
                                            scLastCoverage = 512 - scLastCoverage - 1;
                                        }
                                        #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;
                                            #region prepare for row color index calculation
                                            // get current color index value
                                            dx = (scLastX + 1 - absoluteFocusX);
                                            dxFocusYIncrement = (dx * focusY - dyFocusX);
                                            #endregion


                                            while (startXPosition < lastXPosition)
                                            {
                                                #region calculate color index
                                                currentColorIndexValue =
                                                    (int)
                                                    ((((dx * focusX) + dyFocusY +
                                                        Math.Sqrt(Math.Abs(
                                                            radiusSquared *
                                                            (dx * dx + dySquared) -
                                                            dxFocusYIncrement * dxFocusYIncrement))
                                                            ) * preComputeMultiplyIncludeLookup)
                                                    );

                                                // change for color index calculation
                                                dx++;
                                                dxFocusYIncrement += focusY;
                                                #endregion
                                                colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];
                                                calculatedCoverage = (byte)((colorData >> 24));
                                                calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);
                                                if (calculatedCoverage >= 254)
                                                {
                                                    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 & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                        | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                }
                                                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 - 1;
                                        }
                                        #endregion
                                        // get current color data
                                        #region prepare for row color index calculation
                                        // get current color index value
                                        dx = (currentCellData.X - absoluteFocusX);
                                        dxFocusYIncrement = (dx * focusY - dyFocusX);
                                        #endregion

                                        #region calculate color index
                                        currentColorIndexValue =
                                            (int)
                                            ((((dx * focusX) + dyFocusY +
                                                Math.Sqrt(Math.Abs(
                                                    radiusSquared *
                                                    (dx * dx + dySquared) -
                                                    dxFocusYIncrement * dxFocusYIncrement))
                                                    ) * preComputeMultiplyIncludeLookup)
                                            );
                                        #endregion

                                        colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];//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
                }
                else
                {
                    #region filling without blend for horizontal lines
                    startRowIndex--;
                    while (++startRowIndex <= endRowIndex)
                    {
                        currentCoverage = scLastCoverage = scLastX = 0;
                        #region cumpute value for row
                        //dyFocusY = (startRowIndex - centerY) * (startRowIndex - centerY);
                        dy = ((startRowIndex - centerY) / radiusYForX) - focusY;
                        dySquared = dy * dy;
                        dyFocusX = dy * focusX;
                        dyFocusY = dy * focusY;
                        #endregion
                        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 even odd change
                                        scLastCoverage &= 511;
                                        if (scLastCoverage >= 256)
                                        {
                                            scLastCoverage = 512 - scLastCoverage - 1;
                                        }
                                        #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;
                                            #region prepare for row color index calculation
                                            // get current color index value
                                            dx = (scLastX + 1 - absoluteFocusX);
                                            dxFocusYIncrement = (dx * focusY - dyFocusX);
                                            #endregion


                                            while (startXPosition < lastXPosition)
                                            {
                                                #region calculate color index
                                                currentColorIndexValue =
                                                    (int)
                                                    ((((dx * focusX) + dyFocusY +
                                                        Math.Sqrt(Math.Abs(
                                                            radiusSquared *
                                                            (dx * dx + dySquared) -
                                                            dxFocusYIncrement * dxFocusYIncrement))
                                                            ) * preComputeMultiplyIncludeLookup)
                                                    );

                                                // change for color index calculation
                                                dx++;
                                                dxFocusYIncrement += focusY;
                                                #endregion

                                                colorData = builtColors[currentColorIndexValue < 0 ? 0 : currentColorIndexValue > 254 ? 255 : currentColorIndexValue];
                                                calculatedCoverage = (byte)((colorData >> 24));
                                                calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8);
                                                if (calculatedCoverage >= 254)
                                                {
                                                    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 & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00)
                                                        | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF);
                                                }
                                                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 - 1;
                                        }
                                        #endregion
                                        // get current color data
                                        #region prepare for row color index calculation
                                        // get current color index value
                                        dx = (currentCellData.X - absoluteFocusX);
                                        dxFocusYIncrement = (dx * focusY - dyFocusX);
                                        #endregion

                                        #region calculate color index
                                        currentColorIndexValue =
                                            (int)
                                            ((((dx * focusX) + dyFocusY +
                                                Math.Sqrt(Math.Abs(
                                                    radiusSquared *
                                                    (dx * dx + dySquared) -
                                                    dxFocusYIncrement * dxFocusYIncrement))
                                                    ) * preComputeMultiplyIncludeLookup)
                                            );
                                        #endregion
                                        colorData = builtColors[currentColorIndexValue < 0 ? 0 : currentColorIndexValue > 254 ? 255 : currentColorIndexValue];
                                        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
                }
            }

            #endregion
        }
 /// <summary>
 /// Fill to buffer base rows data information using even odd rule
 /// </summary>
 /// <param name="paint">paint using for fill</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>
 protected abstract void OnFillingEvenOdd(PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue);
 /// <summary>
 /// Fill to buffer base rows data information using even odd rule
 /// </summary>
 /// <param name="paint">paint using for fill</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>
 protected override void OnFillingEvenOdd(PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue)
 {
     // this base on paint to filling
     if (!(paint.Paint is RadialGradient))
     {
         //throw new NotImplementedException("Support color paint only");
         NotMatchPaintTypeException.Publish(typeof(RadialGradient), paint.Paint.GetType());
         return;
     }
     RadialGradient radial = paint.Paint as RadialGradient;
     if (radial.RadiusX == radial.RadiusY)
     {
         if ((radial.FocusX == radial.CenterX) && (radial.FocusY == radial.CenterY))
         {
             // when normal radial gradient
             FillingRadialEvenOdd(radial, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, gammaLutRed, gammaLutGreen, gammaLutBlue);
         }
         else
         {
             // circle and focus gradient
             FillingRadialFocalEvenOdd(radial, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, gammaLutRed, gammaLutGreen, gammaLutBlue);
         }
     }
     else
     {
         if ((radial.FocusX == radial.CenterX) && (radial.FocusY == radial.CenterY))
         {
             // when normal ellipse gradient
             FillingEllipseEvenOdd(radial, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, gammaLutRed, gammaLutGreen, gammaLutBlue);
         }
         else
         {
             // ellipse and focus gradient
             FillingEllipseFocalEvenOdd(radial, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, gammaLutRed, gammaLutGreen, gammaLutBlue);
         }
     }
 }