/// <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>
        void OnFillingHorizontalNonZero(
            LinearGradient paint,
            uint opacity,
            RowData[] rows,
            int startRowIndex,
            int endRowIndex)
        {
            // now not need to check null or not
            uint[] builtColors = paint.GetLinearColors(opacity);

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

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

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

            #endregion

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

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

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

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

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

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

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

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

                                currentCoverage += currentCellData.Coverage;

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

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

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

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

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

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

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

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

                                    #endregion
                                }
                                #endregion

                                scLastCoverage = currentCoverage;
                                scLastX = currentCellData.X;

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

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

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

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

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

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

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

                                currentCoverage += currentCellData.Coverage;

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

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

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

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

                                    #region blend pixel

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

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

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

                                    #endregion
                                }
                                #endregion

                                scLastCoverage = currentCoverage;
                                scLastX = currentCellData.X;

                                // move to next cell
                                currentCellData = currentCellData.Next;
                            } while (currentCellData != null);
                            #endregion
                        }
                    }
                }
                #endregion
            }//has blending color
            #endregion
        }
        /// <summary>
        /// Fill to buffer base rows data information using non-zero rule
        /// </summary>
        /// <param name="paint">linear gradient object</param>
        /// <param name="rows">row data information</param>
        /// <param name="startRowIndex">start row index in row array need to draw</param>
        /// <param name="endRowIndex">end row index in end row array need to draw</param>
        /// <param name="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>
        /// <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
        }