/// <summary> /// Fill to buffer base rows data information using non-zero rule /// </summary> /// <param name="paint">paint using for fill</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> protected override void OnFillingNonZero( PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex) { if (!(paint.Paint is LinearGradient)) { NotMatchPaintTypeException.Publish(typeof(LinearGradient), paint.Paint.GetType()); return; } LinearGradient linearGradient = paint.Paint as LinearGradient; switch (linearGradient.Mode) { case LinearGradientMode.Horizontal: OnFillingHorizontalNonZero(linearGradient, paint.ScaledOpacity, rows, startRowIndex, endRowIndex); break; case LinearGradientMode.Vertical: OnFillingVerticalNonZero(linearGradient, paint.ScaledOpacity, rows, startRowIndex, endRowIndex); break; case LinearGradientMode.ForwardDiagonal: OnFillingDiagonalNonZero(linearGradient, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, true); break; case LinearGradientMode.BackwardDiagonal: OnFillingDiagonalNonZero(linearGradient, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, false); break; } }
/// <summary> /// Filling row data result from start y index to end y index including transformation /// <para>While filling can use CurrentTransformMatrix, or InverterMatrix... to calculate /// or access transformation information</para> /// </summary> /// <param name="paint">paint</param> /// <param name="rows">rows</param> /// <param name="startYIndex">start y index</param> /// <param name="endYIndex">end y index</param> protected override void OnFillingTransformedEvenOdd(PaintMaterial paint, RowData[] rows, int startYIndex, int endYIndex) { throw new NotImplementedException(); }
/// <summary> /// Fill to buffer base rows data information using even odd rule /// </summary> /// <param name="paint">paint using for fill</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> /// <param name="gammaLutRed">gamma look up table for red</param> /// <param name="gammaLutGreen">gamma look up table for green</param> /// <param name="gammaLutBlue">gamma look up table for blue</param> protected override void OnFillingEvenOdd(PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue) { throw new NotImplementedException(); }
/// <summary> /// Filling using radial gradient for circle gradient only /// </summary> /// <param name="radial">radial</param> /// <param name="rows">rows</param> /// <param name="startRowIndex">start y index</param> /// <param name="endRowIndex">end y index</param> /// <param name="gammaLutRed">gamma look up table for red</param> /// <param name="gammaLutGreen">gamma look up table for green</param> /// <param name="gammaLutBlue">gamma look up table for blue</param> void FillingRadialEvenOdd(RadialGradient radial, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue) { // now not need to check null or not uint[] builtColors = radial.GetLinearColors(opacity); #region private variable for filling int currentCoverage, scLastCoverage, scLastX = 0; int tempCover = 0; int currentArea = 0; int lastXPosition = 0; int startXPosition = 0; byte calculatedCoverage = 0; double centerX = radial.CenterX; double centerY = radial.CenterY; // in this case radius x = radius y double radius = radial.RadiusX; // saving precompute value for rows /* Normal calculation to get the color index * currentColorIndexValue = (int)(Math.Sqrt( (startRowIndex - centerY) * (startRowIndex - centerY) + (currentXPosition - centerX) * (currentXPosition - centerX)) * ColorIndexScale / radius ); * but * preComputeForRow= (startRowIndex - centerY) * (startRowIndex - centerY) * so that * currentColorIndexValue = * (int)(Math.Sqrt( (preComputeForRow) + (currentXPosition - centerX) * (currentXPosition - centerX)) * ColorIndexScale / radius ); */ double preComputeForRow = 0; // this is precompute value so that (* ColorIndexScale / radius) now just ( * preComputeRadiusLookup ) double preComputeRadiusLookup = ColorIndexScale / radius; CellData currentCellData = null; uint colorData = 0; //uint colorG = 0; //uint colorRB = 0; int currentColorIndexValue = 0; int currentXPosition = 0; uint dst, dstRB, dstG; #endregion #region FILLING if (radial.Ramp.NoBlendingColor) { // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup if (radial.Style != GradientStyle.Pad) { #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; preComputeForRow = (startRowIndex - centerY) * (startRowIndex - centerY); if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region even odd change scLastCoverage &= 511; if (scLastCoverage >= 256) { scLastCoverage = 512 - scLastCoverage - 1; } #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value //currentColorIndexValue = scLastX + 1 - CurrentStartXIndex; currentXPosition = scLastX + 1; if (scLastCoverage >= 255) { while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int)(Math.Sqrt( preComputeForRow + (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #endregion BufferData[startXPosition] = builtColors[currentColorIndexValue & ColorIndexDoubleMask]; startXPosition++; currentXPosition++; } } else { calculatedCoverage = (byte)scLastCoverage; while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int)(Math.Sqrt( preComputeForRow + (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #endregion colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask]; //calculatedCoverage = (byte)((colorData >> 24)); //calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((((colorData & 0x00FF00FF)) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])) ; #endregion } startXPosition++; currentXPosition++; } } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region even odd change tempCover &= 511; if (tempCover >= 256) { tempCover = 512 - tempCover - 1; } #endregion // get current color data #region calculate color index currentXPosition = currentCellData.X; currentColorIndexValue = (int)(Math.Sqrt(preComputeForRow + (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #endregion colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];//fixedColor[currentCellData.X - CurrentStartXIndex]; //calculatedCoverage = (byte)(colorData >> 24); #region blend pixel //tempCover = (int)((tempCover * calculatedCoverage) >> 8); if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((((colorData & 0x00FF00FF)) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])) ; #endregion } #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion } else { #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; preComputeForRow = (startRowIndex - centerY) * (startRowIndex - centerY); if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region even odd change scLastCoverage &= 511; if (scLastCoverage >= 256) { scLastCoverage = 512 - scLastCoverage - 1; } #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value //currentColorIndexValue = scLastX + 1 - CurrentStartXIndex; currentXPosition = scLastX + 1; if (scLastCoverage >= 255) { while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int)(Math.Sqrt( preComputeForRow + (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #endregion BufferData[startXPosition] = builtColors[currentColorIndexValue > 254 ? 255 : currentColorIndexValue]; startXPosition++; currentXPosition++; } } else { calculatedCoverage = (byte)(scLastCoverage); while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int)(Math.Sqrt( preComputeForRow + (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #endregion colorData = builtColors[currentColorIndexValue > 254 ? 255 : currentColorIndexValue]; //calculatedCoverage = (byte)((colorData >> 24)); //calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { //// blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((((colorData & 0x00FF00FF)) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])) ; #endregion } startXPosition++; currentXPosition++; } } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region even odd change tempCover &= 511; if (tempCover >= 256) { tempCover = 512 - tempCover - 1; } #endregion // get current color data #region calculate color index currentXPosition = currentCellData.X; currentColorIndexValue = (int)(Math.Sqrt(preComputeForRow + (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #endregion colorData = builtColors[currentColorIndexValue > 254 ? 255 : currentColorIndexValue];//fixedColor[currentCellData.X - CurrentStartXIndex]; //calculatedCoverage = (byte)(colorData >> 24); #region blend pixel //tempCover = (int)((tempCover * calculatedCoverage) >> 8); if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((((colorData & 0x00FF00FF)) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])) ; #endregion } #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion } } else { // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup if (radial.Style != GradientStyle.Pad) { #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; preComputeForRow = (startRowIndex - centerY) * (startRowIndex - centerY); if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region even odd change scLastCoverage &= 511; if (scLastCoverage >= 256) { scLastCoverage = 512 - scLastCoverage - 1; } #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value //currentColorIndexValue = scLastX + 1 - CurrentStartXIndex; currentXPosition = scLastX + 1; while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int)(Math.Sqrt( preComputeForRow + (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #endregion colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask]; calculatedCoverage = (byte)((colorData >> 24)); calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((((colorData & 0x00FF00FF)) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])) ; #endregion } startXPosition++; currentXPosition++; } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region even odd change tempCover &= 511; if (tempCover >= 256) { tempCover = 512 - tempCover - 1; } #endregion // get current color data #region calculate color index currentXPosition = currentCellData.X; currentColorIndexValue = (int)(Math.Sqrt(preComputeForRow + (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #endregion colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];//fixedColor[currentCellData.X - CurrentStartXIndex]; calculatedCoverage = (byte)(colorData >> 24); #region blend pixel tempCover = (int)((tempCover * calculatedCoverage) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((((colorData & 0x00FF00FF)) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])) ; #endregion #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion } else { #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; preComputeForRow = (startRowIndex - centerY) * (startRowIndex - centerY); if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region even odd change scLastCoverage &= 511; if (scLastCoverage >= 256) { scLastCoverage = 512 - scLastCoverage - 1; } #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value //currentColorIndexValue = scLastX + 1 - CurrentStartXIndex; currentXPosition = scLastX + 1; while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int)(Math.Sqrt( preComputeForRow + (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #endregion colorData = builtColors[currentColorIndexValue > 254 ? 255 : currentColorIndexValue]; calculatedCoverage = (byte)((colorData >> 24)); calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { //// blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((((colorData & 0x00FF00FF)) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])) ; #endregion } startXPosition++; currentXPosition++; } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region even odd change tempCover &= 511; if (tempCover >= 256) { tempCover = 512 - tempCover - 1; } #endregion // get current color data #region calculate color index currentXPosition = currentCellData.X; currentColorIndexValue = (int)(Math.Sqrt(preComputeForRow + (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #endregion colorData = builtColors[currentColorIndexValue > 254 ? 255 : currentColorIndexValue];//fixedColor[currentCellData.X - CurrentStartXIndex]; calculatedCoverage = (byte)(colorData >> 24); #region blend pixel tempCover = (int)((tempCover * calculatedCoverage) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((((colorData & 0x00FF00FF)) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])) ; #endregion #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion } } #endregion }
/// <summary> /// Fill to buffer base rows data information using non-zero rule /// </summary> /// <param name="paint">linear gradient object</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> /// <param name="gammaLutRed">gamma look up table for red</param> /// <param name="gammaLutGreen">gamma look up table for green</param> /// <param name="gammaLutBlue">gamma look up table for blue</param> void OnFillingVerticalEvenOdd( LinearGradient paint, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue) { // now not need to check null or not uint[] builtColors = paint.GetLinearColors(opacity); /*Base on startX,endX, we need build fixedColor array * contain width count elements. So that, at a column, we * can lookup color for that column. */ #region build fixed color double startY = paint.StartY; double endY = paint.EndY; // width of this int height = endRowIndex - startRowIndex + 1; uint[] fixedColor = new uint[height]; int distanceScaled = (int)(Math.Abs(startY - endY) * DistanceScale); if (distanceScaled == 0) { FillingException.Publish(typeof(LinearGradient), "Start point and end point are too close"); return; } #region building fixed color array if (paint.Style == GradientStyle.Pad) { #region GradientStyle.Pad int startFixedIndex = ((( (((height + startRowIndex) << DistanceShift) - (int)(startY * DistanceScale)) << ColorIndexShift) / distanceScaled)) << IncrementColorIndexShift; int colorIncrement = (DistanceScale * ColorIndexIncludeIncrementScale) / distanceScaled; if (endY < startY) { colorIncrement = -colorIncrement; startFixedIndex = -startFixedIndex; } while (height-- > 0) { fixedColor[height] = builtColors[startFixedIndex < 0 ? 0 : (startFixedIndex > ColorIndexIncludeIncrementScale ? 255 : (startFixedIndex >> IncrementColorIndexShift))]; startFixedIndex -= colorIncrement; } #endregion } else { #region GradientStyle.Repeat || GradientStyle.Reflect int startFixedIndex = ((( (((height + startRowIndex) << DistanceShift) - (int)(startY * DistanceScale)) << ColorIndexShift) / distanceScaled)) << IncrementColorIndexShift; int colorIncrement = (DistanceScale * ColorIndexIncludeIncrementScale) / distanceScaled; if (endY < startY) { colorIncrement = -colorIncrement; } startFixedIndex &= ColorIndexIncludeIncrementDoubleMask; while (height-- > 0) { fixedColor[height] = builtColors[ startFixedIndex < 0 ? (startFixedIndex >> IncrementColorIndexShift) + 512 : (startFixedIndex >> IncrementColorIndexShift)]; startFixedIndex -= colorIncrement; startFixedIndex &= ColorIndexIncludeIncrementDoubleMask; } #endregion } #endregion #endregion #region private variable for filling int currentCoverage, scLastCoverage, scLastX = 0; int tempCover = 0; int currentArea = 0; int lastXPosition = 0; int startXPosition = 0; byte calculatedCoverage = 0; int currentColorIndexValue = 0; CellData currentCellData = null; uint colorData = 0; uint colorAlpha = 0; uint colorG = 0; uint colorRB = 0; uint dst, dstRB, dstG; #endregion #region FILLING if (paint.Ramp.NoBlendingColor) { // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { #region calculate and get current color colorData = fixedColor[currentColorIndexValue]; colorAlpha = (colorData >> 24); colorG = (colorData & 0x0000FF00) >> 8; colorRB = (colorData & 0x00FF00FF); #endregion // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); //#region non-zero checking code //if (scLastCoverage > 255) scLastCoverage = 255; //#endregion #region even-odd change scLastCoverage &= 511; if (scLastCoverage > 256) { scLastCoverage = 512 - scLastCoverage; } #endregion #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value if (scLastCoverage >= 254) { while (startXPosition < lastXPosition) { BufferData[startXPosition++] = colorData; } } else { while (startXPosition < lastXPosition) { calculatedCoverage = (byte)((scLastCoverage * colorAlpha) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)(((((colorRB - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((colorRB - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])); #endregion #endregion } startXPosition++; } } #endregion } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); //#region non-zero checking code //if (tempCover > 255) tempCover = 255; //#endregion #region even-odd change tempCover &= 511; if (tempCover > 256) { tempCover = 512 - tempCover; } #endregion // get current color data #region blend pixel tempCover = (int)((tempCover * colorAlpha) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)(((((colorRB - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((colorRB - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])); #endregion #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } // increase color index currentColorIndexValue++; } #endregion } else { #region perform normal filling startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { #region calculate and get current color colorData = fixedColor[currentColorIndexValue]; colorAlpha = (colorData >> 24); colorG = (colorData & 0x0000FF00) >> 8; colorRB = (colorData & 0x00FF00FF); #endregion // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region even-odd change scLastCoverage &= 511; if (scLastCoverage > 256) { scLastCoverage = 512 - scLastCoverage; } #endregion #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; while (startXPosition < lastXPosition) { calculatedCoverage = (byte)((scLastCoverage * colorAlpha) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)(((((colorRB - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((colorRB - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])); #endregion #endregion } startXPosition++; } #endregion } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region even-odd change tempCover &= 511; if (tempCover > 256) { tempCover = 512 - tempCover; } #endregion #region blend pixel tempCover = (int)((tempCover * colorAlpha) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)(((((colorRB - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = ((((colorRB - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((colorG - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])); #endregion #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } // increase color index currentColorIndexValue++; } #endregion } #endregion }
/// <summary> /// Fill to buffer base rows data information using even odd rule /// </summary> /// <param name="paint">paint using for fill</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> protected abstract void OnFillingEvenOdd(PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex);
/// <summary> /// Filling method including prepare material and perform filling /// </summary> /// <param name="paint">paint</param> /// <param name="rows">rows</param> /// <param name="startYIndex">start y index</param> /// <param name="endYIndex">end y index</param> protected void Filling(PaintMaterial paint, RowData[] rows, int startYIndex, int endYIndex) { //this.CurrentPaint = paint; PrepareMaterial(paint, CurrentStartXIndex, startYIndex, CurrentEndXIndex, endYIndex); OnFilling(paint, rows, startYIndex, endYIndex); OnFinishFilling(); }
/// <summary> /// Rasterize and fill the polygon directly in one pass. This approach is slightly faster than the normal renderation process (Begin, Addxxx, Finish) /// </summary> /// <param name="paint">The paint material used for filling</param> /// <param name="data">raw data array in format [x1,y1, x2,y2, ...]</param> /// <param name="pointCount">Number of points contained within data</param> /// <param name="startOffset">Index of the first point in data </param> /// <param name="offsetX">offseted X</param> /// <param name="offsetY">offseted Y</param> public void FillPolygon(PaintMaterial paint, double[] data, int pointCount, int startOffset, double offsetX, double offsetY) { if (IsClipBoxOutSideBound) { return; } double calculatedX = 0, calculatedY = 0; int endIndex = startOffset + pointCount * 2; #region determine the startY,endY // Start,end y for drawing int endRowPosition = int.MinValue; int startRowPosition = int.MaxValue; CurrentStartXIndex = int.MaxValue; CurrentEndXIndex = int.MinValue; for (int i = startOffset; i < endIndex; i += 2) { calculatedX = data[i] + offsetX; calculatedY = data[i + 1] + offsetY; if (calculatedX > CurrentEndXIndex) { CurrentEndXIndex = (int)calculatedX + 1; } if (calculatedX < CurrentStartXIndex) { CurrentStartXIndex = (int)calculatedX; } if (calculatedY > endRowPosition) { endRowPosition = (int)calculatedY + 1; } if (calculatedY < startRowPosition) { startRowPosition = (int)calculatedY; } } #endregion #region prepare Rows array startRowPosition--; endRowPosition++; if (startRowPosition < ClippingBoxYMin) { startRowPosition = (int)ClippingBoxYMin; } if (endRowPosition > ClippingBoxYMax + 1) { endRowPosition = (int)ClippingBoxYMax + 1; } for (int rowIndex = startRowPosition; rowIndex <= endRowPosition; rowIndex++) { Rows[rowIndex] = new RowData(); } #endregion #region draw lines CurrentXPosition = data[startOffset] + offsetX; CurrentYPosition = data[startOffset + 1] + offsetY; CurrentPositionFlag = ((CurrentXPosition > ClippingBoxXMax) ? XMaxClippingFlag : (CurrentXPosition < ClippingBoxXMin) ? XMinClippingFlag : 0) | ((CurrentYPosition > ClippingBoxYMax) ? YMaxClippingFlag : (CurrentYPosition < ClippingBoxYMin) ? YMinClippingFlag : 0); for (int i = startOffset + 2; i < endIndex; i += 2) { if (CurrentYPosition != data[i + 1] + offsetY) { DrawAndClippedLine(data[i] + offsetX, data[i + 1] + offsetY); } else { // just move to and calculate the flag CurrentXPosition = data[i] + offsetX; CurrentYPosition = data[i + 1] + offsetY; CurrentPositionFlag = ((CurrentXPosition > ClippingBoxXMax) ? XMaxClippingFlag : (CurrentXPosition < ClippingBoxXMin) ? XMinClippingFlag : 0) | ((CurrentYPosition > ClippingBoxYMax) ? YMaxClippingFlag : (CurrentYPosition < ClippingBoxYMin) ? YMinClippingFlag : 0); } } if (CurrentYPosition != data[startOffset + 1] + offsetY) { DrawAndClippedLine(data[startOffset] + offsetX, data[startOffset + 1] + offsetY); } #endregion #region fill Filling(paint, Rows, startRowPosition, endRowPosition); #endregion }
/// <summary> /// Fill to buffer base rows data information using non zero rule /// </summary> /// <param name="paint">paint using for fill</param> /// <param name="rows">row data information</param> /// <param name="startYIndex">start row index in row array need to draw</param> /// <param name="endYIndex">end row index in end row array need to draw</param> protected void OnBuildingNonZero(RowData[] rows, int startYIndex, int endYIndex) { #region private variable for filling int currentCoverage, scLastCoverage, scLastX = 0; int tempCover = 0; int currentArea = 0; int lastXPosition = 0; int startXPosition = 0; CellData currentCellData = null; byte calculatedCoverage = 0; byte[] MaskData = mResultMask.Data; int maskStartOffset = mResultMask.StartOffset; int maskStride = mResultMask.Stride; #endregion startYIndex--; while (++startYIndex <= endYIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startYIndex] != null) { // get first cell in current row currentCellData = rows[startYIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region this check for non zero case if (scLastCoverage > 255) scLastCoverage = 255; #endregion //fill from currentX position to last x position //scLastCoverage = (byte)((scLastCoverage * colorAlpha) >> 8); #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = maskStartOffset + startYIndex * maskStride + scLastX + 1; lastXPosition = maskStartOffset + startYIndex * maskStride + currentCellData.X; calculatedCoverage = (byte)scLastCoverage; while (startXPosition < lastXPosition) { MaskData[startXPosition++] = calculatedCoverage; } #endregion } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // calculate tempcover tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region this check using for non zero if (tempCover > 255) tempCover = 255; #endregion startXPosition = maskStartOffset + startYIndex * maskStride + currentCellData.X; MaskData[startXPosition] = (byte)tempCover; } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } }
/// <summary> /// Build mask base on rows result of rasterizer /// </summary> /// <param name="rows">rasterized result</param> /// <param name="startRowPosition">start row</param> /// <param name="endRowPosition">end row</param> protected void BuildMask(RowData[] rows, int startRowPosition, int endRowPosition) { if (mFillingRule == FillingRule.NonZero) { OnBuildingNonZero(rows, startRowPosition, endRowPosition); } else { OnBuildingEvenOdd(rows, startRowPosition, endRowPosition); } }
/// <summary> /// Fill to buffer base rows data information using non-zero rule /// </summary> /// <param name="paint">linear gradient object</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> /// <param name="isForward">is diagonal gradient is forward</param> /// <param name="gammaLutRed">gamma look up table for red</param> /// <param name="gammaLutGreen">gamma look up table for green</param> /// <param name="gammaLutBlue">gamma look up table for blue</param> void OnFillingTransformedDiagonalNonZero(LinearGradient paint, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex, bool isForward, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue) { throw new NotImplementedException(); }
/// <summary> /// Fill to buffer base rows data information using non-zero rule /// </summary> /// <param name="paint">linear gradient object</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> /// <param name="gammaLutRed">gamma look up table for red</param> /// <param name="gammaLutGreen">gamma look up table for green</param> /// <param name="gammaLutBlue">gamma look up table for blue</param> void OnFillingTransformedVerticalNonZero(LinearGradient paint, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue) { // now not need to check null or not uint[] builtColors = paint.GetLinearColors(opacity); #region private variable for filling int currentCoverage, scLastCoverage, scLastX = 0; int tempCover = 0; int currentArea = 0; int lastXPosition = 0; int startXPosition = 0; byte calculatedCoverage = 0; int currentColorIndexScaled = 0; CellData currentCellData = null; uint colorData = 0; uint dst, dstRB, dstG; //uint colorG = 0; //uint colorRB = 0; // each row color index will increase value double startRowIncrement = 0; #endregion #region varialbe for vertical double startY = paint.StartY; double endY = paint.EndY; double distance = endY - startY; #endregion #region variable for transform #region transform line 1,1 => 101,1 double currentYTransformed = 1 * InvertedMatrixShy + 1 * InvertedMatrixSy + InvertedMatrixTy; double destYToTransformed = 101 * InvertedMatrixShy + 1 * InvertedMatrixSy + InvertedMatrixTy; #endregion // in vertical we need increment by x after steps double transformedRatio = (destYToTransformed - currentYTransformed) / 100; // when transformed horizonline increase 1, x will increase by increment. int incrementTranformedColorIndexScaled = (int)((transformedRatio / distance) * ColorIndexIncludeIncrementScale); #endregion #region prepare value for rows //transform first cell of row currentYTransformed = startRowIndex * InvertedMatrixSy + InvertedMatrixTy; currentYTransformed = ((currentYTransformed - startY) / distance); //calculate row increment startRowIncrement = ((InvertedMatrixSy / distance)); #endregion #region FILLING if (paint.Ramp.NoBlendingColor) {// no blending color if (paint.Style != GradientStyle.Pad) { #region optimized for reflect and repeat mode incrementTranformedColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; if (incrementTranformedColorIndexScaled < 0) { incrementTranformedColorIndexScaled = ColorIndexIncludeIncrementDoubleScale - incrementTranformedColorIndexScaled; } #endregion // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { #region transform for row currentColorIndexScaled = (int) (currentYTransformed * ColorIndexIncludeIncrementScale); if (currentColorIndexScaled < 0) { currentColorIndexScaled += ColorIndexIncludeIncrementDoubleScale; } currentYTransformed += startRowIncrement; #endregion // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1)) { if (scLastCoverage != 0) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region non-zero checking code if (scLastCoverage > 255) scLastCoverage = 255; #endregion #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value if (scLastCoverage >= 254) { while (startXPosition < lastXPosition) { //BufferData[startXPosition++] = colorData; //BufferData[startXPosition++] = builtColors[(currentColorIndexScaled >> IncrementColorIndexShift) ]; BufferData[startXPosition++] = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift]; // incre color index currentColorIndexScaled += incrementTranformedColorIndexScaled; //currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; } } else { while (startXPosition < lastXPosition) { colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift]; // incre color index currentColorIndexScaled += incrementTranformedColorIndexScaled; calculatedCoverage = (byte)((colorData >> 24)); calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 255) { BufferData[startXPosition] = colorData; } else { //// blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])); #endregion } startXPosition++; currentColorIndexScaled++; } } #endregion } else { // incre color index currentColorIndexScaled += (currentCellData.X - scLastX - 1) * incrementTranformedColorIndexScaled; } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region non-zero checking code if (tempCover > 255) tempCover = 255; #endregion colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift]; calculatedCoverage = (byte)(colorData >> 24); #region blend pixel tempCover = (int)((tempCover * calculatedCoverage) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])); #endregion #endregion #endregion } #endregion // incre color index currentColorIndexScaled += incrementTranformedColorIndexScaled; scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion } else {//GradientStyle.Pad mode #region GradientStyle.Pad // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { #region transform for row currentColorIndexScaled = (int) (currentYTransformed * ColorIndexIncludeIncrementScale); //if (currentColorIndexScaled < 0) //{ // currentColorIndexScaled += ColorIndexIncludeIncrementDoubleScale; //} currentYTransformed += startRowIncrement; #endregion // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1)) { if (scLastCoverage != 0) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region non-zero checking code if (scLastCoverage > 255) scLastCoverage = 255; #endregion #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value if (scLastCoverage >= 254) { while (startXPosition < lastXPosition) { //BufferData[startXPosition++] = colorData; //BufferData[startXPosition++] = builtColors[(currentColorIndexScaled >> IncrementColorIndexShift) ]; BufferData[startXPosition++] = builtColors[ currentColorIndexScaled < 0 ? 0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 : currentColorIndexScaled >> IncrementColorIndexShift)]; // incre color index currentColorIndexScaled += incrementTranformedColorIndexScaled; //currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; } } else { while (startXPosition < lastXPosition) { //colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift]; colorData = builtColors[ currentColorIndexScaled < 0 ? 0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 : currentColorIndexScaled >> IncrementColorIndexShift)]; // incre color index currentColorIndexScaled += incrementTranformedColorIndexScaled; calculatedCoverage = (byte)((colorData >> 24)); calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 255) { BufferData[startXPosition] = colorData; } else { // blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])); #endregion } startXPosition++; currentColorIndexScaled++; } } #endregion } else { // incre color index currentColorIndexScaled += (currentCellData.X - scLastX - 1) * incrementTranformedColorIndexScaled; } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region non-zero checking code if (tempCover > 255) tempCover = 255; #endregion colorData = builtColors[ currentColorIndexScaled < 0 ? 0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 : currentColorIndexScaled >> IncrementColorIndexShift)]; calculatedCoverage = (byte)(colorData >> 24); #region blend pixel tempCover = (int)((tempCover * calculatedCoverage) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])); #endregion #endregion #endregion } #endregion // incre color index currentColorIndexScaled += incrementTranformedColorIndexScaled; scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion #endregion }//GradientStyle.Pad mode }// no blending color else {// has blending color if (paint.Style != GradientStyle.Pad) { #region optimized for reflect and repeat mode incrementTranformedColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; if (incrementTranformedColorIndexScaled < 0) { incrementTranformedColorIndexScaled = ColorIndexIncludeIncrementDoubleScale - incrementTranformedColorIndexScaled; } #endregion // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { #region transform for row currentColorIndexScaled = (int) (currentYTransformed * ColorIndexIncludeIncrementScale); if (currentColorIndexScaled < 0) { currentColorIndexScaled += ColorIndexIncludeIncrementDoubleScale; } currentYTransformed += startRowIncrement; #endregion // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1)) { if (scLastCoverage != 0) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region non-zero checking code if (scLastCoverage > 255) scLastCoverage = 255; #endregion #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; while (startXPosition < lastXPosition) { colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift]; currentColorIndexScaled += incrementTranformedColorIndexScaled; calculatedCoverage = (byte)(colorData >> 24); calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | ((uint)gammaLutBlue[(dstRB & 0x00FF)])); #endregion #endregion } startXPosition++; currentColorIndexScaled++; } #endregion } else { // incre color index currentColorIndexScaled += (currentCellData.X - scLastX - 1) * incrementTranformedColorIndexScaled; } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region non-zero checking code if (tempCover > 255) tempCover = 255; #endregion colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift]; calculatedCoverage = (byte)(colorData >> 24); #region blend pixel tempCover = (int)((tempCover * calculatedCoverage) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | (gammaLutBlue[(dstRB & 0x00FF)])); #endregion #endregion #endregion } #endregion // incre color index currentColorIndexScaled += incrementTranformedColorIndexScaled; scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion } else { #region GradientStyle.Pad // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { #region transform for row currentColorIndexScaled = (int) (currentYTransformed * ColorIndexIncludeIncrementScale); //if (currentColorIndexScaled < 0) //{ // currentColorIndexScaled += ColorIndexIncludeIncrementDoubleScale; //} currentYTransformed += startRowIncrement; #endregion // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1)) { if (scLastCoverage != 0) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region non-zero checking code if (scLastCoverage > 255) scLastCoverage = 255; #endregion #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; while (startXPosition < lastXPosition) { //colorData = builtColors[(currentColorIndexScaled & ColorIndexIncludeIncrementDoubleMask) >> IncrementColorIndexShift]; colorData = builtColors[ currentColorIndexScaled < 0 ? 0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 : currentColorIndexScaled >> IncrementColorIndexShift)]; currentColorIndexScaled += incrementTranformedColorIndexScaled; calculatedCoverage = (byte)(colorData >> 24); calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (((uint)gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | ((uint)gammaLutBlue[(dstRB & 0x00FF)])); #endregion #endregion } startXPosition++; currentColorIndexScaled++; } #endregion } else { // incre color index currentColorIndexScaled += (currentCellData.X - scLastX - 1) * incrementTranformedColorIndexScaled; } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region non-zero checking code if (tempCover > 255) tempCover = 255; #endregion colorData = builtColors[ currentColorIndexScaled < 0 ? 0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 : currentColorIndexScaled >> IncrementColorIndexShift)]; calculatedCoverage = (byte)(colorData >> 24); #region blend pixel tempCover = (int)((tempCover * calculatedCoverage) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here //dst = BufferData[startXPosition]; //dstRB = dst & 0x00FF00FF; //dstG = (dst >> 8) & 0xFF; //BufferData[startXPosition] = // (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) // | (uint)((((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) // | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #region gamma apply dst = BufferData[startXPosition]; dstG = (dst >> 8) & 0xFF; dstRB = (((((colorData & 0x00FF00FF) - (dst & 0x00FF00FF)) * calculatedCoverage) >> 8) + (dst & 0x00FF00FF)); BufferData[startXPosition] = (uint)((AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | ((uint)(gammaLutGreen[(((((((colorData & 0xFF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) & 0xFF)] << 8)) | ((uint)gammaLutRed[(dstRB & 0x00FF0000) >> 16] << 16) | ((uint)gammaLutBlue[(dstRB & 0x00FF)])); #endregion #endregion #endregion } #endregion // incre color index currentColorIndexScaled += incrementTranformedColorIndexScaled; scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion #endregion } }//has blending color #endregion }
/// <summary> /// Fill to buffer base rows data information using non-zero rule /// </summary> /// <param name="paint">linear gradient object</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> /// <param name="isForward">is diagonal gradient is forward</param> void OnFillingDiagonalNonZero( LinearGradient paint, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex, bool isForward) { #region Explain for fomula /* * CALCULATION NEED FOLLOWING VALUES * 1/ INCREMENT * increment, when x from n to n+1 , * index of color will increase from * f(n) to f(n) + increment * * this increment value is calculated by * Linear from A to B * A C B' * * * * * * * * * * * * * * * * * * * * * * B * AC = w of the rect * BB' |_ AB * So AB' = (AB * AB)/AC = d * d / w * And increment is increment = 256 / AB' * it mean when x go from A to B' * color index will increase from 0=>255 ( 256 steps) * * * 2/ DISTANCE * (x3,y3) * * * * * * * * * * * * * * * (x1,y1)* * * * * * * * (x2,y2) * * x3,y3 can be calculated by following fomula * x3 = x1 - height of paint = x1 - ( y2- y1); * y3 = y1 + width of paint = y1 + ( x2 - x1); * * to determine color at point(x,y) to line (x1,y1)-(x3,y3) * from this distance we can determine the color at this * point by lookup to color array * * distance = ((x - x3) * (y3-y1) * - ( y - y3) * (x3 -x1))/(distance from start and end point of paint); */ #endregion #region Pre-process double x1 = 0; double y1 = 0; double x2 = 0; double y2 = 0; if (isForward) { x1 = paint.StartX; y1 = paint.StartY; x2 = paint.EndX; y2 = paint.EndY; } else { x1 = paint.EndX; y1 = paint.StartY; x2 = paint.StartX; y2 = paint.EndY; } double widthOfPaint = x2 - x1; double heightOfPaint = y2 - y1; //note: start and end point is random // start not always on top-left // so width of paint and height of paint may be negative if (widthOfPaint == 0) { // this will change to vertical OnFillingVerticalNonZero(paint, opacity, rows, startRowIndex, endRowIndex); return; } else if (heightOfPaint == 0) { // this will change to horizontal OnFillingHorizontalNonZero(paint, opacity, rows, startRowIndex, endRowIndex); return; } #endregion #region calculate the increasement double x3 = x1 - heightOfPaint; double y3 = y1 + widthOfPaint; double lengthOfPaint = Math.Sqrt((widthOfPaint * widthOfPaint) + (heightOfPaint * heightOfPaint)); //int distanceOfPaintScaled = (int)(distanceOfPaint * DistanceScale); double incrementColorIndex = (double)(widthOfPaint * ColorIndexScale) / (lengthOfPaint * lengthOfPaint); // increment by distance scale // increment may be greater than 512, but in reflect,repeat mode, // just modulo it // get the remain when divide by 512 // incrementColorIndex = incrementColorIndex - (((int)incrementColorIndex / ColorIndexDoubleScale) * ColorIndexDoubleScale); //incrementX < 512, calculate incrementIndex // ( that scale by 256 for approxiate calculation ) int scaledIncrementColorIndex = (int)(incrementColorIndex * IncrementColorIndexScale); #endregion // now not need to check null or not uint[] builtColors = paint.GetLinearColors(opacity); #region private variable for filling int currentCoverage, scLastCoverage, scLastX = 0; int tempCover = 0; int currentArea = 0; int lastXPosition = 0; int startXPosition = 0; byte calculatedCoverage = 0; // this color index is scaled int currentColorIndexScaled = 0; CellData currentCellData = null; uint colorData = 0; uint dst, dstRB, dstG; double firstPointDistance = 0; #endregion #region optimization for color index // the ORIGIN fomula for each row, we need to calculate this //firstPointDistance = (((x3) * (y3 - y1) - (startRowIndex - y3) * (x3 - x1)) / distanceOfPaint); //// color index = (distance from point to line => scaled) * 256/ (distance of paint scaled) //currentColorIndexScaled = // (int)((firstPointDistance * ColorIndexIncludeIncrementScale / distanceOfPaint)); // currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; // mod ( 512 << 8) // now we need calculate for first time only and after a row, we need to add and small value //firstPointDistance is x value when line cut the horizontal at position startRowIndex //firstPointDistance = (((x3) * (y3 - y1) - (startRowIndex - y3) * (x3 - x1)) /(lengthOfPaint)); // y = slope * x + beta //=> slope * x - y + beta = 0 double slope = (y3 - y1) / (x3 - x1); double beta = (y3 - slope * x3); // fomula to calculate distance from point to line a*x + b*y + c= 0 // is d = (a*x1 + b*y1 + c) / sqrt(a*a + b*b) // in this case d = (slope * x1 + (-1) * y1 + beta) / sqrt ( slope * slope + (-1) * (-1)) //firstPointDistance = (-startRowIndex + beta) / Math.Sqrt(slope * slope + 1); //http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html firstPointDistance = ((x3 - x1) * (y1 - startRowIndex) - (x1 - 0) * (y3 - y1)) / lengthOfPaint; int startOfRowIndex = (int)((firstPointDistance * ColorIndexIncludeIncrementScale / lengthOfPaint)); int rowColorIndexIncrementScaled = (int)(((-(x3 - x1) / lengthOfPaint) * ColorIndexIncludeIncrementScale / lengthOfPaint)); #endregion #region FILLING if (paint.Ramp.NoBlendingColor) { if (paint.Style != GradientStyle.Pad) { #region GradientStyle.Reflect || GradientStyle.Repeat // in case reflect and repeat, we don't care value that out of range startOfRowIndex &= ColorIndexIncludeIncrementDoubleMask; rowColorIndexIncrementScaled &= ColorIndexIncludeIncrementDoubleMask; scaledIncrementColorIndex &= ColorIndexIncludeIncrementDoubleMask; #region filling without blend for horizontal lines // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { // calculate the first cell color index #region second way to implement color index currentColorIndexScaled = startOfRowIndex; #endregion #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1)) { if (scLastCoverage != 0) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region non-zero checking code if (scLastCoverage > 255) scLastCoverage = 255; #endregion #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value if (scLastCoverage >= 254) { while (startXPosition < lastXPosition) { BufferData[startXPosition] = builtColors[currentColorIndexScaled < 0 ? (currentColorIndexScaled >> IncrementColorIndexShift) + 512 : (currentColorIndexScaled >> IncrementColorIndexShift)]; startXPosition++; // increase current color index currentColorIndexScaled += scaledIncrementColorIndex; currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; } } else { calculatedCoverage = (byte)scLastCoverage; while (startXPosition < lastXPosition) { dst = BufferData[startXPosition]; colorData = builtColors[currentColorIndexScaled < 0 ? (currentColorIndexScaled >> IncrementColorIndexShift) + 512 : (currentColorIndexScaled >> IncrementColorIndexShift)]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); startXPosition++; // increase the current color index currentColorIndexScaled += scaledIncrementColorIndex; currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; } } #endregion } else { // not filling but must set and increase the color index currentColorIndexScaled += (currentCellData.X - scLastX - 1) * scaledIncrementColorIndex; currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region non-zero checking code if (tempCover > 255) tempCover = 255; #endregion // get current color data #region blend pixel //tempCover = (int)((tempCover * colorAlpha) >> 8); ////if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here dst = BufferData[startXPosition]; colorData = builtColors[currentColorIndexScaled < 0 ? (currentColorIndexScaled >> IncrementColorIndexShift) + 512 : (currentColorIndexScaled >> IncrementColorIndexShift)]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion #endregion } #endregion // alway increment color index currentColorIndexScaled += scaledIncrementColorIndex; currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; // assign value for next loop scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } #region each row we need increase the value of color index startOfRowIndex += rowColorIndexIncrementScaled; startOfRowIndex &= ColorIndexIncludeIncrementDoubleMask; #endregion } #endregion #endregion }//Reflect or Repeat mode else {//Pad mode #region GradientStyle.Pad // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { // calculate the first cell color index #region second way to implement color index currentColorIndexScaled = startOfRowIndex; #endregion #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1)) { if (scLastCoverage != 0) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region non-zero checking code if (scLastCoverage > 255) scLastCoverage = 255; #endregion #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value if (scLastCoverage >= 254) { while (startXPosition < lastXPosition) { BufferData[startXPosition] = builtColors[ currentColorIndexScaled < 0 ? 0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 : (currentColorIndexScaled >> IncrementColorIndexShift))]; startXPosition++; // increase current color index currentColorIndexScaled += scaledIncrementColorIndex; } } else { calculatedCoverage = (byte)scLastCoverage; while (startXPosition < lastXPosition) { colorData = builtColors[ currentColorIndexScaled < 0 ? 0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 : (currentColorIndexScaled >> IncrementColorIndexShift))]; #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion startXPosition++; // increase the current color index currentColorIndexScaled += scaledIncrementColorIndex; } } #endregion } else { // not filling but must set and increase the color index currentColorIndexScaled += (currentCellData.X - scLastX - 1) * scaledIncrementColorIndex; } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region non-zero checking code if (tempCover > 255) tempCover = 255; #endregion // get current color data #region blend pixel calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here dst = BufferData[startXPosition]; colorData = builtColors[ currentColorIndexScaled < 0 ? 0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 : (currentColorIndexScaled >> IncrementColorIndexShift))]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion #endregion } #endregion // alway increment color index currentColorIndexScaled += scaledIncrementColorIndex; // assign value for next loop scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } #region each row we need increase the value of color index startOfRowIndex += rowColorIndexIncrementScaled; #endregion } #endregion }//Pad mode }//paint.Ramp.NoBlendingColor else {//has blending color // blending include alpha of built color if (paint.Style != GradientStyle.Pad) { #region GradientStyle.Reflect || GradientStyle.Repeat // in case reflect and repeat, we don't care value that out of range startOfRowIndex &= ColorIndexIncludeIncrementDoubleMask; rowColorIndexIncrementScaled &= ColorIndexIncludeIncrementDoubleMask; // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { // calculate the first cell color index #region second way to implement color index currentColorIndexScaled = startOfRowIndex; #endregion #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1)) { if (scLastCoverage != 0) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region non-zero checking code if (scLastCoverage > 255) scLastCoverage = 255; #endregion #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; while (startXPosition < lastXPosition) { colorData = builtColors[currentColorIndexScaled < 0 ? (currentColorIndexScaled >> IncrementColorIndexShift) + 512 : (currentColorIndexScaled >> IncrementColorIndexShift)]; // get current color index value calculatedCoverage = (byte)(((colorData >> 24) * scLastCoverage) >> 8); #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); startXPosition++; #endregion // increase the current color index currentColorIndexScaled += scaledIncrementColorIndex; currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; } #endregion } else { // not filling but must set and increase the color index currentColorIndexScaled += (currentCellData.X - scLastX - 1) * scaledIncrementColorIndex; currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region non-zero checking code if (tempCover > 255) tempCover = 255; #endregion // get current color data #region blend pixel //tempCover = (int)((tempCover * colorAlpha) >> 8); ////if (tempCover > 255) tempCover = 255; //calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here colorData = builtColors[currentColorIndexScaled < 0 ? (currentColorIndexScaled >> IncrementColorIndexShift) + 512 : (currentColorIndexScaled >> IncrementColorIndexShift)]; calculatedCoverage = (byte)(((colorData >> 24) * tempCover) >> 8); dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion #endregion } #endregion // alway increment color index currentColorIndexScaled += scaledIncrementColorIndex; currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; // assign value for next loop scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } #region each row we need increase the value of color index startOfRowIndex += rowColorIndexIncrementScaled; startOfRowIndex &= ColorIndexIncludeIncrementDoubleMask; #endregion } #endregion #endregion }//Reflect or Repeat mode else {//Pad mode #region GradientStyle.Pad // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { // calculate the first cell color index #region second way to implement color index currentColorIndexScaled = startOfRowIndex; #endregion #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1)) { if (scLastCoverage != 0) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region non-zero checking code if (scLastCoverage > 255) scLastCoverage = 255; #endregion #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value while (startXPosition < lastXPosition) { colorData = builtColors[currentColorIndexScaled < 0 ? 0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 : (currentColorIndexScaled >> IncrementColorIndexShift))]; calculatedCoverage = (byte)(((colorData >> 24) * scLastCoverage) >> 8); #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion startXPosition++; // increase the current color index currentColorIndexScaled += scaledIncrementColorIndex; //currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; } #endregion } else { // not filling but must set and increase the color index currentColorIndexScaled += (currentCellData.X - scLastX - 1) * scaledIncrementColorIndex; //currentColorIndexScaled &= ColorIndexIncludeIncrementDoubleMask; } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region non-zero checking code if (tempCover > 255) tempCover = 255; #endregion // get current color data #region blend pixel //calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here colorData = builtColors[currentColorIndexScaled < 0 ? 0 : (currentColorIndexScaled > ColorIndexIncludeIncrementScale ? 255 : (currentColorIndexScaled >> IncrementColorIndexShift))]; calculatedCoverage = (byte)(((colorData >> 24) * tempCover) >> 8); dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x0000FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)((((((colorData & 0x00FF00FF) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion #endregion } #endregion // alway increment color index currentColorIndexScaled += scaledIncrementColorIndex; // assign value for next loop scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } #region each row we need increase the value of color index startOfRowIndex += rowColorIndexIncrementScaled; #endregion } #endregion }//Pad mode }//has blending color #endregion }
/// <summary> /// Fill to buffer base rows data information using non-zero rule /// </summary> /// <param name="paint">linear gradient object</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> void OnFillingHorizontalNonZero( LinearGradient paint, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex) { // now not need to check null or not uint[] builtColors = paint.GetLinearColors(opacity); /* Base on startX, endX, we need build fixedColor array * contain width-count elements. So that, at a column, * we can lookup color for that column. */ #region Build fixed color double startX = paint.StartX; double endX = paint.EndX; // width of this int width = CurrentEndXIndex - CurrentStartXIndex + 1; uint[] fixedColor = new uint[width]; int distanceScaled = (int)(Math.Abs(startX - endX) * DistanceScale); if (distanceScaled == 0) { FillingException.Publish(typeof(LinearGradient), "Start point and end point are too close"); return; } #region build fixed-color array if (paint.Style == GradientStyle.Pad) { #region GradientStyle.Pad int startXScaled = (int)(startX * DistanceScale); int startFixedIndex = ((( (((width + CurrentStartXIndex) << DistanceShift) - startXScaled) << ColorIndexShift) / distanceScaled)) << IncrementColorIndexShift; int colorIncrement = (DistanceScale * ColorIndexIncludeIncrementScale) / distanceScaled; if (endX < startX) { colorIncrement = -colorIncrement; startFixedIndex = -startFixedIndex; } while (width-- > 0) { fixedColor[width] = builtColors[ startFixedIndex < 0 ? 0 : (startFixedIndex > ColorIndexIncludeIncrementScale ? 255 : (startFixedIndex >> IncrementColorIndexShift))]; startFixedIndex -= colorIncrement; } #endregion } else { #region GradientStyle.Repeat || GradientStyle.Reflect int startXScaled = (int)(startX * DistanceScale); int startFixedIndex = ((( (((width + CurrentStartXIndex) << DistanceShift) - startXScaled) << ColorIndexShift) / distanceScaled)) << IncrementColorIndexShift; int colorIncrement = (DistanceScale * ColorIndexIncludeIncrementScale) / distanceScaled; if (endX < startX) { colorIncrement = -colorIncrement; } startFixedIndex &= ColorIndexIncludeIncrementDoubleMask; while (width-- > 0) { fixedColor[width] = builtColors[ startFixedIndex < 0 ? (startFixedIndex >> IncrementColorIndexShift) + 512 : (startFixedIndex >> IncrementColorIndexShift)]; startFixedIndex -= colorIncrement; startFixedIndex &= ColorIndexIncludeIncrementDoubleMask; } #endregion } #endregion #endregion #region private variable for filling int currentCoverage, scLastCoverage, scLastX = 0; int tempCover = 0; int currentArea = 0; int lastXPosition = 0; int startXPosition = 0; byte calculatedCoverage = 0; int currentColorIndexValue = 0; CellData currentCellData = null; uint colorData = 0; uint dst, dstRB, dstG; #endregion #region FILLING if (paint.Ramp.NoBlendingColor) { #region filling without blend for horizontal lines // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region non-zero checking code if (scLastCoverage > 255) scLastCoverage = 255; #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value currentColorIndexValue = scLastX + 1 - CurrentStartXIndex; if (scLastCoverage >= 255) { while (startXPosition < lastXPosition) { BufferData[startXPosition++] = fixedColor[currentColorIndexValue++]; } } else { while (startXPosition < lastXPosition) { colorData = fixedColor[currentColorIndexValue]; calculatedCoverage = (byte)((colorData >> 24)); calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 255) { BufferData[startXPosition] = colorData; } else { #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion } startXPosition++; currentColorIndexValue++; } } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region non-zero checking code if (tempCover > 255) tempCover = 255; #endregion // get current color data colorData = fixedColor[currentCellData.X - CurrentStartXIndex]; calculatedCoverage = (byte)(colorData >> 24); #region blend pixel tempCover = (int)((tempCover * calculatedCoverage) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion }//paint.Ramp.NoBlendingColor else {//has blending color #region perform normal filling startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region non-zero checking code if (scLastCoverage > 255) scLastCoverage = 255; #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; // get current color index value currentColorIndexValue = scLastX + 1 - CurrentStartXIndex; while (startXPosition < lastXPosition) { colorData = fixedColor[currentColorIndexValue]; calculatedCoverage = (byte)(colorData >> 24); calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 255) { BufferData[startXPosition] = colorData; } else { #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion } startXPosition++; currentColorIndexValue++; } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region non-zero checking code if (tempCover > 255) tempCover = 255; #endregion // get current color data colorData = fixedColor[currentCellData.X - CurrentStartXIndex]; calculatedCoverage = (byte)(colorData >> 24); #region blend pixel tempCover = (int)((tempCover * calculatedCoverage) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion }//has blending color #endregion }
/// <summary> /// Filling row data result from start y index to end y index including transformation /// <para>While filling can use CurrentTransformMatrix, or InverterMatrix... to calculate /// or access transformation information</para> /// </summary> /// <param name="paint">paint</param> /// <param name="rows">rows</param> /// <param name="startYIndex">start y index</param> /// <param name="endYIndex">end y index</param> protected override void OnFillingTransformedNonZero( PaintMaterial paint, RowData[] rows, int startYIndex, int endYIndex) { if (!(paint.Paint is LinearGradient)) { //throw new NotImplementedException("Support color paint only"); NotMatchPaintTypeException.Publish(typeof(LinearGradient), paint.Paint.GetType()); return; } LinearGradient linearGradient = paint.Paint as LinearGradient; switch (linearGradient.Mode) { case LinearGradientMode.Horizontal: OnFillingTransformedHorizontalNonZero(linearGradient, paint.ScaledOpacity, rows, startYIndex, endYIndex); break; case LinearGradientMode.Vertical: OnFillingTransformedVerticalNonZero(linearGradient, paint.ScaledOpacity, rows, startYIndex, endYIndex); break; case LinearGradientMode.ForwardDiagonal: OnFillingTransformedDiagonalNonZero(linearGradient, paint.ScaledOpacity, rows, startYIndex, endYIndex, true); break; case LinearGradientMode.BackwardDiagonal: OnFillingTransformedDiagonalNonZero(linearGradient, paint.ScaledOpacity, rows, startYIndex, endYIndex, false); break; } }
/// <summary> /// Filling row data result from start y index to end y index including transformation /// <para>While filling can use CurrentTransformMatrix, or InverterMatrix... to calculate /// or access transformation information</para> /// </summary> /// <param name="paint">paint</param> /// <param name="rows">rows</param> /// <param name="startYIndex">start y index</param> /// <param name="endYIndex">end y index</param> /// <param name="gammaLutRed">gamma look up table for red</param> /// <param name="gammaLutGreen">gamma look up table for green</param> /// <param name="gammaLutBlue">gamma look up table for blue</param> protected override void OnFillingTransformedNonZero(PaintMaterial paint, RowData[] rows, int startYIndex, int endYIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue) { throw new NotImplementedException(); }
/// <summary> /// Fill to buffer base rows data information using non zero rule /// </summary> /// <param name="paint">paint using for fill</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> protected override void OnFillingNonZero(PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex) { throw new NotImplementedException(); }
/// <summary> /// Fill to buffer base rows data information using EvenOdd rule /// </summary> /// <param name="paint">paint using for fill</param> /// <param name="rows">row data information</param> /// <param name="startYIndex">start row index in row array need to draw</param> /// <param name="endYIndex">end row index in end row array need to draw</param> protected void OnBuildingEvenOdd(RowData[] rows, int startYIndex, int endYIndex) { #region private variable for filling int currentCoverage, scLastCoverage, scLastX = 0; int tempCover = 0; int currentArea = 0; int lastXPosition = 0; int startXPosition = 0; CellData currentCellData = null; byte calculatedCoverage = 0; byte[] MaskData = mResultMask.Data; int maskStartOffset = mResultMask.StartOffset; int maskStride = mResultMask.Stride; #endregion startYIndex--; while (++startYIndex <= endYIndex) { currentCoverage = scLastCoverage = scLastX = 0; if (rows[startYIndex] != null) { // get first cell in current row currentCellData = rows[startYIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region even odd change //scLastCoverage &= 511; //if (scLastCoverage > 256) //{ // scLastCoverage = 512 - scLastCoverage; //} scLastCoverage &= 511; if (scLastCoverage >= 256) { scLastCoverage = 512 - scLastCoverage - 1; } #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = maskStartOffset + startYIndex * maskStride + scLastX + 1; lastXPosition = maskStartOffset + startYIndex * maskStride + currentCellData.X; calculatedCoverage = (byte)scLastCoverage; while (startXPosition < lastXPosition) { MaskData[startXPosition++] = calculatedCoverage; } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); //tempCover &= 511; //if (tempCover >= 256) //{ // tempCover = 512 - tempCover; //} #region even odd change tempCover &= 511; if (tempCover >= 256) { tempCover = 512 - tempCover - 1; } #endregion if (tempCover != 0) { startXPosition = maskStartOffset + startYIndex * maskStride + currentCellData.X; MaskData[startXPosition] = (byte)tempCover; } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } }
// ======= VIRTUAL METHODS #region PrepareBuffer /// <summary> /// Preparing buffer and internal data for using /// </summary> /// <param name="buffer">buffer</param> protected virtual void PrepareBuffer(PixelsBuffer buffer) { //automatically create a new boundary to match this buffer if (mBuffer == null) { //mBoundary = Boundary.Empty; DestBufferWidth = 0; DestBufferHeight = 0; BufferStride = 0; BufferStartOffset = 0; BufferData = null; } else { //mBoundary = new Boundary(mBuffer.Width, mBuffer.Height); DestBufferWidth = mBuffer.Width; DestBufferHeight = mBuffer.Height; BufferStride = mBuffer.Stride; BufferStartOffset = mBuffer.StartOffset; BufferData = mBuffer.Data; //mPixelRenderer.PixelBuffer = mBuffer; } if ((Rows == null) || (Rows.Length < DestBufferHeight + 1)) { Rows = new RowData[DestBufferHeight + 1]; } SetClip(0, 0, DestBufferWidth, DestBufferHeight); }
/// <summary> /// Rasterize and fill the polygon directly in one pass. This approach is slightly faster than the normal renderation process (Begin, Addxxx, Finish) /// </summary> /// <param name="paint">The paint material used for filling</param> /// <param name="data">raw data array in format [x1,y1, x2,y2, ...]</param> /// <param name="pointCount">Number of points contained within data</param> /// <param name="startOffset">Index of the first point in data </param> /// <param name="offsetX">offseted X</param> /// <param name="offsetY">offseted Y</param> public void FillPolygon(PaintMaterial paint, double[] data, int pointCount, int startOffset, double offsetX, double offsetY) { if (IsClipBoxOutSideBound) { return; } double calculatedX = 0, calculatedY = 0; int endIndex = startOffset + pointCount * 2; #region determine the startY,endY // Start,end y for drawing int endRowPosition = int.MinValue; int startRowPosition = int.MaxValue; CurrentStartXIndex = int.MaxValue; CurrentEndXIndex = int.MinValue; for (int i = startOffset; i < endIndex; i += 2) { calculatedX = data[i] + offsetX; calculatedY = data[i + 1] + offsetY; if (calculatedX > CurrentEndXIndex) { CurrentEndXIndex = (int)calculatedX + 1; } if (calculatedX < CurrentStartXIndex) { CurrentStartXIndex = (int)calculatedX; } if (calculatedY > endRowPosition) { endRowPosition = (int)calculatedY + 1; } if (calculatedY < startRowPosition) { startRowPosition = (int)calculatedY; } } #endregion #region prepare Rows array startRowPosition--; endRowPosition++; if (startRowPosition < ClippingBoxYMin) { startRowPosition = (int)ClippingBoxYMin; } if (endRowPosition > ClippingBoxYMax + 1) { endRowPosition = (int)ClippingBoxYMax + 1; } for (int rowIndex = startRowPosition; rowIndex <= endRowPosition; rowIndex++) { Rows[rowIndex] = new RowData(); } #endregion #region draw lines CurrentXPosition = data[startOffset] + offsetX; CurrentYPosition = data[startOffset + 1] + offsetY; CurrentPositionFlag = ((CurrentXPosition > ClippingBoxXMax) ? XMaxClippingFlag : (CurrentXPosition < ClippingBoxXMin) ? XMinClippingFlag : 0) | ((CurrentYPosition > ClippingBoxYMax) ? YMaxClippingFlag : (CurrentYPosition < ClippingBoxYMin) ? YMinClippingFlag : 0); for (int i = startOffset + 2; i < endIndex; i += 2) { if (CurrentYPosition != data[i + 1] + offsetY) { DrawAndClippedLine(data[i] + offsetX, data[i + 1] + offsetY); } else { // just move to and calculate the flag CurrentXPosition = data[i] + offsetX; CurrentYPosition = data[i + 1] + offsetY; CurrentPositionFlag = ((CurrentXPosition > ClippingBoxXMax) ? XMaxClippingFlag : (CurrentXPosition < ClippingBoxXMin) ? XMinClippingFlag : 0) | ((CurrentYPosition > ClippingBoxYMax) ? YMaxClippingFlag : (CurrentYPosition < ClippingBoxYMin) ? YMinClippingFlag : 0); } } if (CurrentYPosition != data[startOffset + 1] + offsetY) { DrawAndClippedLine(data[startOffset] + offsetX, data[startOffset + 1] + offsetY); } #endregion #region fill BuildMask(Rows, startRowPosition, endRowPosition); //Filling(paint, Rows, startRowPosition, endRowPosition); #endregion }
/// <summary> /// Perform filling into rasterized result /// </summary> /// <param name="paint">paint</param> /// <param name="rows">rows</param> /// <param name="startYIndex">start y index</param> /// <param name="endYIndex">end y index</param> protected virtual void OnFilling(PaintMaterial paint, RowData[] rows, int startYIndex, int endYIndex) { //outside of box, no need to fill if (IsClipBoxOutSideBound) return; //Cross.Log.Debug("Start row {0}, end rows {1}",startYIndex,endYIndex); // when gamma function is assigned and gamma function need to apply //if ((mGamma != null) &&(mGamma.IsAppliedGamma)) if ((mGamma != null)) { if (paint.FillingRule == FillingRule.NonZero) { // fill non-zero including gamma OnFillingNonZero(paint, Rows, startYIndex, endYIndex, mGamma.GetLookupTableRed(), mGamma.GetLookupTableGreen(), mGamma.GetLookupTableBlue()); } else { // fill Even-Odd including gamma OnFillingEvenOdd(paint, Rows, startYIndex, endYIndex, mGamma.GetLookupTableRed(), mGamma.GetLookupTableGreen(), mGamma.GetLookupTableBlue()); } } else { //Cross.Log.Debug("Filling without gamma"); if (paint.FillingRule == FillingRule.NonZero) { OnFillingNonZero(paint, Rows, startYIndex, endYIndex); } else { OnFillingEvenOdd(paint, Rows, startYIndex, endYIndex); } } }
/// <summary> /// Filling using radial gradient for circle gradient only /// </summary> /// <param name="radial">radial</param> /// <param name="rows">rows</param> /// <param name="startRowIndex">start y index</param> /// <param name="endRowIndex">end y index</param> void FillingEllipseFocalEvenOdd(RadialGradient radial, uint opacity, RowData[] rows, int startRowIndex, int endRowIndex) { // now not need to check null or not uint[] builtColors = radial.GetLinearColors(opacity); #region private variable for filling int currentCoverage, scLastCoverage, scLastX = 0; int tempCover = 0; int currentArea = 0; int lastXPosition = 0; int startXPosition = 0; byte calculatedCoverage = 0; double centerX = radial.CenterX; double centerY = radial.CenterY; // in this case radius x = radius y double radius = radial.RadiusX; double radiusYForX = radial.RadiusY / radial.RadiusX; // this is precompute value so that (* ColorIndexScale / radius) now just ( * preComputeRadiusLookup ) double preComputeRadiusLookup = ColorIndexScale / radius; CellData currentCellData = null; uint colorData = 0; double dx = 0, dy = 0; double dySquared = 0; // saving dy * dy // focus is changed to relative from the center double absoluteFocusX = radial.FocusX; double absoluteFocusY = radial.FocusY; double focusX = radial.FocusX - centerX; double focusY = radial.FocusY - centerY; focusY = focusY / radiusYForX; // note that dx,dy need to move center /* * dx = (currentXPosition - absoluteFocusX); * dy = (startRowIndex - absoluteFocusY); * currentColorIndexValue = (int) ( ( ( (dx * focusX) + (dy * focusY) + Math.Sqrt ( Math.Abs ( radius * radius * (dx * dx + dy * dy) - (dx * focusY - dy * focusX) * (dx * focusY - dy * focusX) ) ) ) * (radius / ((radius * radius) - ((focusX * focusX )+ (focusY * focusY)))) ) * 256 /radius ); */ //note that ( radius / (( radius * radius) - ((focusX * focusX) + (focusY * focusY))) is const // so that need to pre compute double preComputeMultiply = radius / ((radius * radius) - ((focusX * focusX) + (focusY * focusY))); #region modify when pre compute for multiply is zero if (preComputeMultiply == 0) { if (focusX != 0) { if (focusX < 0) { focusX += GradientAdjustment; } else { focusX -= GradientAdjustment; } } if (focusY != 0) { if (focusY < 0) { focusY += GradientAdjustment; } else { focusY -= GradientAdjustment; } } preComputeMultiply = radius / ((radius * radius) - ((focusX * focusX) + (focusY * focusY))); } #endregion double preComputeMultiplyIncludeLookup = preComputeRadiusLookup * preComputeMultiply; // saving dy * focusY double dyFocusY = 0; double dyFocusX = 0; double dxFocusYIncrement = 0; // saving dx * focusY - dyFocusX double radiusSquared = radius * radius; int currentColorIndexValue = 0; //int currentXPosition = 0; uint dst, dstRB, dstG; #endregion #region FILLING if (radial.Ramp.NoBlendingColor) { // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup if (radial.Style != GradientStyle.Pad) { #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; #region cumpute value for row //dyFocusY = (startRowIndex - centerY) * (startRowIndex - centerY); dy = ((startRowIndex - centerY) / radiusYForX) - focusY; dySquared = dy * dy; dyFocusX = dy * focusX; dyFocusY = dy * focusY; #endregion if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region even odd change scLastCoverage &= 511; if (scLastCoverage >= 256) { scLastCoverage = 512 - scLastCoverage - 1; } #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region prepare for row color index calculation // get current color index value //currentColorIndexValue = scLastX + 1 - CurrentStartXIndex; //currentXPosition = scLastX + 1; dx = (scLastX + 1 - absoluteFocusX); dxFocusYIncrement = (dx * focusY - dyFocusX); #endregion if (scLastCoverage >= 255) { while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int) ((((dx * focusX) + dyFocusY + Math.Sqrt(Math.Abs( radiusSquared * (dx * dx + dySquared) - dxFocusYIncrement * dxFocusYIncrement)) ) * preComputeMultiplyIncludeLookup) ); //currentColorIndexValue = // (int) // ( // ( // ( // (dx * focusX) + (dy * focusY) // + Math.Sqrt // ( // Math.Abs // ( // radius * radius // * (dx * dx + dy * dy) // - (dx * focusY - dy * focusX) // * (dx * focusY - dy * focusX) // ) // ) // ) * (radius / // ((radius * radius) - ((focusX * focusX) + (focusY * focusY)))) // ) * 256 / radius // ); // change for color index calculation dx++; dxFocusYIncrement += focusY; #endregion BufferData[startXPosition] = builtColors[currentColorIndexValue & ColorIndexDoubleMask]; startXPosition++; } } else { calculatedCoverage = (byte)scLastCoverage; while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int) ((((dx * focusX) + dyFocusY + Math.Sqrt(Math.Abs( radiusSquared * (dx * dx + dySquared) - dxFocusYIncrement * dxFocusYIncrement)) ) * preComputeMultiplyIncludeLookup) ); // change for color index calculation dx++; dxFocusYIncrement += focusY; #endregion colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask]; //calculatedCoverage = (byte)((colorData >> 24)); //calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { // blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); } startXPosition++; } } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region even odd change tempCover &= 511; if (tempCover >= 256) { tempCover = 512 - tempCover - 1; } #endregion // get current color data #region calculate color index //currentXPosition = currentCellData.X; //currentColorIndexValue = // (int)(Math.Sqrt(dyFocusY + // (currentXPosition - centerX) * (currentXPosition - centerX)) * preComputeRadiusLookup); #region prepare for row color index calculation // get current color index value dx = (currentCellData.X - absoluteFocusX); dxFocusYIncrement = (dx * focusY - dyFocusX); #endregion #region calculate color index currentColorIndexValue = (int) ((((dx * focusX) + dyFocusY + Math.Sqrt(Math.Abs( radiusSquared * (dx * dx + dySquared) - dxFocusYIncrement * dxFocusYIncrement)) ) * preComputeMultiplyIncludeLookup) ); #endregion #endregion colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];//fixedColor[currentCellData.X - CurrentStartXIndex]; //calculatedCoverage = (byte)(colorData >> 24); #region blend pixel //tempCover = (int)((tempCover * calculatedCoverage) >> 8); if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion } else { #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; #region cumpute value for row //dyFocusY = (startRowIndex - centerY) * (startRowIndex - centerY); dy = ((startRowIndex - centerY) / radiusYForX) - focusY; dySquared = dy * dy; dyFocusX = dy * focusX; dyFocusY = dy * focusY; #endregion if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region even odd change scLastCoverage &= 511; if (scLastCoverage >= 256) { scLastCoverage = 512 - scLastCoverage - 1; } #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region prepare for row color index calculation // get current color index value dx = (scLastX + 1 - absoluteFocusX); dxFocusYIncrement = (dx * focusY - dyFocusX); #endregion if (scLastCoverage >= 255) { while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int) ((((dx * focusX) + dyFocusY + Math.Sqrt(Math.Abs( radiusSquared * (dx * dx + dySquared) - dxFocusYIncrement * dxFocusYIncrement)) ) * preComputeMultiplyIncludeLookup) ); // change for color index calculation dx++; dxFocusYIncrement += focusY; #endregion BufferData[startXPosition] = builtColors[currentColorIndexValue < 0 ? 0 : currentColorIndexValue > 254 ? 255 : currentColorIndexValue]; startXPosition++; } } else { calculatedCoverage = (byte)(scLastCoverage); while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int) ((((dx * focusX) + dyFocusY + Math.Sqrt(Math.Abs( radiusSquared * (dx * dx + dySquared) - dxFocusYIncrement * dxFocusYIncrement)) ) * preComputeMultiplyIncludeLookup) ); // change for color index calculation dx++; dxFocusYIncrement += focusY; #endregion colorData = builtColors[currentColorIndexValue < 0 ? 0 : currentColorIndexValue > 254 ? 255 : currentColorIndexValue]; //calculatedCoverage = (byte)((colorData >> 24)); //calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { // blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); } startXPosition++; } } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region even odd change tempCover &= 511; if (tempCover >= 256) { tempCover = 512 - tempCover - 1; } #endregion // get current color data #region calculate color index #region prepare for row color index calculation // get current color index value dx = (currentCellData.X - absoluteFocusX); dxFocusYIncrement = (dx * focusY - dyFocusX); #endregion #region calculate color index currentColorIndexValue = (int) ((((dx * focusX) + dyFocusY + Math.Sqrt(Math.Abs( radiusSquared * (dx * dx + dySquared) - dxFocusYIncrement * dxFocusYIncrement)) ) * preComputeMultiplyIncludeLookup) ); #endregion #endregion colorData = builtColors[currentColorIndexValue < 0 ? 0 : currentColorIndexValue > 254 ? 255 : currentColorIndexValue]; //calculatedCoverage = (byte)(colorData >> 24); #region blend pixel //tempCover = (int)((tempCover * calculatedCoverage) >> 8); if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion } } else { // when no need to blending, when draw a horizontal line // do not need check the back color, alway setup if (radial.Style != GradientStyle.Pad) { #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; #region cumpute value for row //dyFocusY = (startRowIndex - centerY) * (startRowIndex - centerY); dy = ((startRowIndex - centerY) / radiusYForX) - focusY; dySquared = dy * dy; dyFocusX = dy * focusX; dyFocusY = dy * focusY; #endregion if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region even odd change scLastCoverage &= 511; if (scLastCoverage >= 256) { scLastCoverage = 512 - scLastCoverage - 1; } #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region prepare for row color index calculation // get current color index value dx = (scLastX + 1 - absoluteFocusX); dxFocusYIncrement = (dx * focusY - dyFocusX); #endregion while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int) ((((dx * focusX) + dyFocusY + Math.Sqrt(Math.Abs( radiusSquared * (dx * dx + dySquared) - dxFocusYIncrement * dxFocusYIncrement)) ) * preComputeMultiplyIncludeLookup) ); // change for color index calculation dx++; dxFocusYIncrement += focusY; #endregion colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask]; calculatedCoverage = (byte)((colorData >> 24)); calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { // blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); } startXPosition++; } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region even odd change tempCover &= 511; if (tempCover >= 256) { tempCover = 512 - tempCover - 1; } #endregion // get current color data #region prepare for row color index calculation // get current color index value dx = (currentCellData.X - absoluteFocusX); dxFocusYIncrement = (dx * focusY - dyFocusX); #endregion #region calculate color index currentColorIndexValue = (int) ((((dx * focusX) + dyFocusY + Math.Sqrt(Math.Abs( radiusSquared * (dx * dx + dySquared) - dxFocusYIncrement * dxFocusYIncrement)) ) * preComputeMultiplyIncludeLookup) ); #endregion colorData = builtColors[currentColorIndexValue & ColorIndexDoubleMask];//fixedColor[currentCellData.X - CurrentStartXIndex]; calculatedCoverage = (byte)(colorData >> 24); #region blend pixel tempCover = (int)((tempCover * calculatedCoverage) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion } else { #region filling without blend for horizontal lines startRowIndex--; while (++startRowIndex <= endRowIndex) { currentCoverage = scLastCoverage = scLastX = 0; #region cumpute value for row //dyFocusY = (startRowIndex - centerY) * (startRowIndex - centerY); dy = ((startRowIndex - centerY) / radiusYForX) - focusY; dySquared = dy * dy; dyFocusX = dy * focusX; dyFocusY = dy * focusY; #endregion if (rows[startRowIndex] != null) { // get first cell in current row currentCellData = rows[startRowIndex].First; if (currentCellData != null) { #region fill current row do { currentArea = currentCellData.Area; #region blend horizontal line if ((currentCellData.X > scLastX + 1) && (scLastCoverage != 0)) { // fast bit absolute scLastCoverage = (scLastCoverage ^ (scLastCoverage >> 31)) - (scLastCoverage >> 31); #region even odd change scLastCoverage &= 511; if (scLastCoverage >= 256) { scLastCoverage = 512 - scLastCoverage - 1; } #endregion if (scLastCoverage != 0) { #region BLEND HORIZONTAL LINE // calculate start and end position startXPosition = BufferStartOffset + startRowIndex * BufferStride + scLastX + 1; lastXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region prepare for row color index calculation // get current color index value dx = (scLastX + 1 - absoluteFocusX); dxFocusYIncrement = (dx * focusY - dyFocusX); #endregion while (startXPosition < lastXPosition) { #region calculate color index currentColorIndexValue = (int) ((((dx * focusX) + dyFocusY + Math.Sqrt(Math.Abs( radiusSquared * (dx * dx + dySquared) - dxFocusYIncrement * dxFocusYIncrement)) ) * preComputeMultiplyIncludeLookup) ); // change for color index calculation dx++; dxFocusYIncrement += focusY; #endregion colorData = builtColors[currentColorIndexValue < 0 ? 0 : currentColorIndexValue > 254 ? 255 : currentColorIndexValue]; calculatedCoverage = (byte)((colorData >> 24)); calculatedCoverage = (byte)((scLastCoverage * calculatedCoverage) >> 8); if (calculatedCoverage >= 254) { BufferData[startXPosition] = colorData; } else { // blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); } startXPosition++; } #endregion } } #endregion currentCoverage += currentCellData.Coverage; #region blend the current cell // fast absolute tempCover = ((currentCoverage << 9) - currentArea) >> 9; if (tempCover != 0) { // fast bit absolute tempCover = (tempCover ^ (tempCover >> 31)) - (tempCover >> 31); #region even odd change tempCover &= 511; if (tempCover >= 256) { tempCover = 512 - tempCover - 1; } #endregion // get current color data #region prepare for row color index calculation // get current color index value dx = (currentCellData.X - absoluteFocusX); dxFocusYIncrement = (dx * focusY - dyFocusX); #endregion #region calculate color index currentColorIndexValue = (int) ((((dx * focusX) + dyFocusY + Math.Sqrt(Math.Abs( radiusSquared * (dx * dx + dySquared) - dxFocusYIncrement * dxFocusYIncrement)) ) * preComputeMultiplyIncludeLookup) ); #endregion colorData = builtColors[currentColorIndexValue < 0 ? 0 : currentColorIndexValue > 254 ? 255 : currentColorIndexValue]; calculatedCoverage = (byte)(colorData >> 24); #region blend pixel tempCover = (int)((tempCover * calculatedCoverage) >> 8); //if (tempCover > 255) tempCover = 255; calculatedCoverage = (byte)tempCover; startXPosition = BufferStartOffset + startRowIndex * BufferStride + currentCellData.X; #region blend here dst = BufferData[startXPosition]; dstRB = dst & 0x00FF00FF; dstG = (dst >> 8) & 0xFF; BufferData[startXPosition] = (uint)(AlphaCache[(((dst >> 24) & 0xFF) << 8) + calculatedCoverage]) | (uint)((((((((colorData & 0x00FF00) >> 8) - dstG) * calculatedCoverage) >> 8) + dstG) << 8) & 0x0000FF00) | (uint)(((((((colorData & 0x00FF00FF)) - dstRB) * calculatedCoverage) >> 8) + dstRB) & 0x00FF00FF); #endregion #endregion } #endregion scLastCoverage = currentCoverage; scLastX = currentCellData.X; // move to next cell currentCellData = currentCellData.Next; } while (currentCellData != null); #endregion } } } #endregion } } #endregion }
/// <summary> /// Fill to buffer base rows data information using even odd rule /// </summary> /// <param name="paint">paint using for fill</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> /// <param name="gammaLutRed">gamma look up table for red</param> /// <param name="gammaLutGreen">gamma look up table for green</param> /// <param name="gammaLutBlue">gamma look up table for blue</param> protected abstract void OnFillingEvenOdd(PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue);
/// <summary> /// Fill to buffer base rows data information using even odd rule /// </summary> /// <param name="paint">paint using for fill</param> /// <param name="rows">row data information</param> /// <param name="startRowIndex">start row index in row array need to draw</param> /// <param name="endRowIndex">end row index in end row array need to draw</param> /// <param name="gammaLutRed">gamma look up table for red</param> /// <param name="gammaLutGreen">gamma look up table for green</param> /// <param name="gammaLutBlue">gamma look up table for blue</param> protected override void OnFillingEvenOdd(PaintMaterial paint, RowData[] rows, int startRowIndex, int endRowIndex, byte[] gammaLutRed, byte[] gammaLutGreen, byte[] gammaLutBlue) { // this base on paint to filling if (!(paint.Paint is RadialGradient)) { //throw new NotImplementedException("Support color paint only"); NotMatchPaintTypeException.Publish(typeof(RadialGradient), paint.Paint.GetType()); return; } RadialGradient radial = paint.Paint as RadialGradient; if (radial.RadiusX == radial.RadiusY) { if ((radial.FocusX == radial.CenterX) && (radial.FocusY == radial.CenterY)) { // when normal radial gradient FillingRadialEvenOdd(radial, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, gammaLutRed, gammaLutGreen, gammaLutBlue); } else { // circle and focus gradient FillingRadialFocalEvenOdd(radial, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, gammaLutRed, gammaLutGreen, gammaLutBlue); } } else { if ((radial.FocusX == radial.CenterX) && (radial.FocusY == radial.CenterY)) { // when normal ellipse gradient FillingEllipseEvenOdd(radial, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, gammaLutRed, gammaLutGreen, gammaLutBlue); } else { // ellipse and focus gradient FillingEllipseFocalEvenOdd(radial, paint.ScaledOpacity, rows, startRowIndex, endRowIndex, gammaLutRed, gammaLutGreen, gammaLutBlue); } } }