#![allow(unused_parens)]
use crate::aacoverage::{CCoverageBuffer, c_rInvShiftSize, c_antiAliasMode, c_nShift, CCoverageInterval, c_nShiftMask, c_nShiftSize, c_nHalfShiftSize};
use crate::hwvertexbuffer::CHwVertexBufferBuilder;
use crate::matrix::{CMILMatrix, CMatrix};
use crate::nullable_ref::Ref;
use crate::aarasterizer::*;
use crate::geometry_sink::IGeometrySink;
use crate::helpers::Int32x32To64;
use crate::types::*;
use typed_arena_nomut::Arena;
macro_rules! MIL_THR {
($e: expr) => {
$e }
}
fn IsFractionGreaterThan(
nNumeratorA: INT, nDenominatorA: INT, nNumeratorB: INT, nDenominatorB: INT, ) -> bool
{
let lNumeratorAxDenominatorB = Int32x32To64(nNumeratorA, nDenominatorB);
let lNumeratorBxDenominatorA = Int32x32To64(nNumeratorB, nDenominatorA);
return (lNumeratorAxDenominatorB > lNumeratorBxDenominatorA);
}
fn
IsFractionLessThan(
nNumeratorA: INT, nDenominatorA: INT, nNumeratorB: INT, nDenominatorB: INT, ) -> bool
{
let lNumeratorAxDenominatorB = Int32x32To64(nNumeratorA, nDenominatorB);
let lNumeratorBxDenominatorA = Int32x32To64(nNumeratorB, nDenominatorA);
return (lNumeratorAxDenominatorB < lNumeratorBxDenominatorA);
}
fn
AdvanceDDAMultipleSteps(
pEdgeLeft: &CEdge, pEdgeRight: &CEdge, nSubpixelYAdvance: INT, nSubpixelXLeftBottom: &mut INT, nSubpixelErrorLeftBottom: &mut INT, nSubpixelXRightBottom: &mut INT, nSubpixelErrorRightBottom: &mut INT )
{
#[cfg(debug_assertions)]
{
let nDbgPixelCoordinateMax = (1 << 26);
let nDbgPixelCoordinateMin = -nDbgPixelCoordinateMax;
assert!(pEdgeLeft.X.get() >= nDbgPixelCoordinateMin && pEdgeLeft.X.get() <= nDbgPixelCoordinateMax);
assert!(pEdgeLeft.EndY >= nDbgPixelCoordinateMin && pEdgeLeft.EndY <= nDbgPixelCoordinateMax);
assert!(pEdgeRight.X.get() >= nDbgPixelCoordinateMin && pEdgeRight.X.get() <= nDbgPixelCoordinateMax);
assert!(pEdgeRight.EndY >= nDbgPixelCoordinateMin && pEdgeRight.EndY <= nDbgPixelCoordinateMax);
let nDbgErrorDownMax: INT = (1 << 30);
assert!(pEdgeLeft.ErrorDown > 0 && pEdgeLeft.ErrorDown < nDbgErrorDownMax);
assert!(pEdgeRight.ErrorDown > 0 && pEdgeRight.ErrorDown < nDbgErrorDownMax);
assert!(pEdgeLeft.ErrorUp >= 0 && pEdgeLeft.ErrorUp < pEdgeLeft.ErrorDown);
assert!(pEdgeRight.ErrorUp >= 0 && pEdgeRight.ErrorUp < pEdgeRight.ErrorDown);
}
*nSubpixelXLeftBottom = pEdgeLeft.X.get() + nSubpixelYAdvance*pEdgeLeft.Dx;
let mut llSubpixelErrorBottom: LONGLONG = pEdgeLeft.Error.get() as LONGLONG + Int32x32To64(nSubpixelYAdvance, pEdgeLeft.ErrorUp);
if (llSubpixelErrorBottom >= 0)
{
let llSubpixelXLeftDelta = llSubpixelErrorBottom / (pEdgeLeft.ErrorDown as LONGLONG);
assert!(llSubpixelXLeftDelta < INT::MAX as LONGLONG);
let nSubpixelXLeftDelta: INT = (llSubpixelXLeftDelta as INT) + 1;
*nSubpixelXLeftBottom += nSubpixelXLeftDelta;
llSubpixelErrorBottom -= Int32x32To64(pEdgeLeft.ErrorDown, nSubpixelXLeftDelta);
}
assert!((llSubpixelErrorBottom > -pEdgeLeft.ErrorDown as LONGLONG) && (llSubpixelErrorBottom < 0));
*nSubpixelErrorLeftBottom = (llSubpixelErrorBottom as INT);
*nSubpixelXRightBottom = pEdgeRight.X.get() + nSubpixelYAdvance*pEdgeRight.Dx;
llSubpixelErrorBottom = pEdgeRight.Error.get() as LONGLONG + Int32x32To64(nSubpixelYAdvance, pEdgeRight.ErrorUp);
if (llSubpixelErrorBottom >= 0)
{
let llSubpixelXRightDelta: LONGLONG = llSubpixelErrorBottom / (pEdgeRight.ErrorDown as LONGLONG);
assert!(llSubpixelXRightDelta < INT::MAX as LONGLONG);
let nSubpixelXRightDelta: INT = (llSubpixelXRightDelta as INT) + 1;
*nSubpixelXRightBottom += nSubpixelXRightDelta;
llSubpixelErrorBottom -= Int32x32To64(pEdgeRight.ErrorDown, nSubpixelXRightDelta);
}
assert!((llSubpixelErrorBottom > -pEdgeRight.ErrorDown as LONGLONG) && (llSubpixelErrorBottom < 0));
*nSubpixelErrorRightBottom = (llSubpixelErrorBottom as INT);
}
fn
ComputeDeltaUpperBound(
pEdge: &CEdge, nSubpixelYAdvance: INT ) -> INT
{
let nSubpixelDeltaUpperBound: INT;
if (pEdge.ErrorUp == 0)
{
nSubpixelDeltaUpperBound = nSubpixelYAdvance*(pEdge.Dx).abs();
}
else
{
let nAbsDx: INT;
let nAbsErrorUp: INT;
assert!(pEdge.ErrorUp > 0);
if (pEdge.Dx >= 0)
{
nAbsDx = pEdge.Dx;
nAbsErrorUp = pEdge.ErrorUp;
}
else
{
nAbsDx = -pEdge.Dx - 1;
nAbsErrorUp = -pEdge.ErrorUp + pEdge.ErrorDown;
}
nSubpixelDeltaUpperBound = nSubpixelYAdvance*nAbsDx + (nSubpixelYAdvance*nAbsErrorUp)/pEdge.ErrorDown + 1;
}
return nSubpixelDeltaUpperBound;
}
fn
ComputeDistanceLowerBound(
pEdgeLeft: &CEdge, pEdgeRight: &CEdge ) -> INT
{
assert!(pEdgeLeft.Error.get() < 0);
assert!(pEdgeRight.Error.get() < 0);
assert!(pEdgeLeft.X <= pEdgeRight.X);
let mut nSubpixelXDistanceLowerBound: INT = pEdgeRight.X.get() - pEdgeLeft.X.get();
if (IsFractionLessThan(
pEdgeRight.Error.get()+1,
pEdgeRight.ErrorDown,
pEdgeLeft.Error.get()+1,
pEdgeLeft.ErrorDown
))
{
nSubpixelXDistanceLowerBound -= 1;
}
return nSubpixelXDistanceLowerBound;
}
pub struct CHwRasterizer<'x, 'y, 'z> {
m_rcClipBounds: MilPointAndSizeL,
m_matWorldToDevice: CMILMatrix,
m_pIGeometrySink: &'x mut CHwVertexBufferBuilder<'y, 'z>,
m_fillMode: MilFillMode,
}
fn ConvertSubpixelXToPixel(
x: INT,
error: INT,
rErrorDown: f32
) -> f32
{
assert!(rErrorDown > f32::EPSILON);
return ((x as f32) + (error as f32)/rErrorDown)*c_rInvShiftSize;
}
fn ConvertSubpixelYToPixel(
nSubpixel: i32
) -> f32
{
return (nSubpixel as f32)*c_rInvShiftSize;
}
impl<'x, 'y, 'z> CHwRasterizer<'x, 'y, 'z> {
pub fn RasterizePath(
&mut self,
rgpt: &[POINT],
rgTypes: &[BYTE],
cPoints: UINT,
pmatWorldTransform: &CMILMatrix
) -> HRESULT
{
let mut hr;
let mut inactiveArrayStack: [CInactiveEdge; INACTIVE_LIST_NUMBER!()] = [(); INACTIVE_LIST_NUMBER!()].map(|_| Default::default());
let mut pInactiveArray: &mut [CInactiveEdge];
let mut pInactiveArrayAllocation: Vec<CInactiveEdge>;
let mut edgeHead: CEdge = Default::default();
let mut edgeTail: CEdge = Default::default();
let pEdgeActiveList: Ref<CEdge>;
let mut edgeStore = Arena::new();
let mut edgeContext: CInitializeEdgesContext = CInitializeEdgesContext::new(&mut edgeStore);
edgeContext.ClipRect = None;
edgeTail.X.set(i32::MAX); edgeTail.StartY = i32::MAX;
edgeTail.EndY = i32::MIN;
edgeHead.X.set(i32::MIN); edgeContext.MaxY = i32::MIN;
edgeHead.Next.set(Ref::new(&edgeTail));
pEdgeActiveList = Ref::new(&mut edgeHead);
edgeContext.AntiAliasMode = c_antiAliasMode;
assert!(edgeContext.AntiAliasMode != MilAntiAliasMode::None);
if (cPoints < 2)
{
return S_OK;
}
let nPixelYClipBottom: INT = self.m_rcClipBounds.Y + self.m_rcClipBounds.Height;
let mut clipBounds : RECT = Default::default();
clipBounds.left = self.m_rcClipBounds.X * FIX4_ONE!();
clipBounds.top = self.m_rcClipBounds.Y * FIX4_ONE!();
clipBounds.right = (self.m_rcClipBounds.X + self.m_rcClipBounds.Width) * FIX4_ONE!();
clipBounds.bottom = (self.m_rcClipBounds.Y + self.m_rcClipBounds.Height) * FIX4_ONE!();
edgeContext.ClipRect = Some(&clipBounds);
let mut matrix: CMILMatrix = (*pmatWorldTransform).clone();
AppendScaleToMatrix(&mut matrix, TOREAL!(16), TOREAL!(16));
let coverageBuffer: CCoverageBuffer = Default::default();
coverageBuffer.Initialize();
hr = MIL_THR!(FixedPointPathEnumerate(
rgpt,
rgTypes,
cPoints,
&matrix,
edgeContext.ClipRect,
&mut edgeContext
));
if (FAILED(hr))
{
if (hr == WGXERR_VALUEOVERFLOW)
{
hr = S_OK;
}
return hr;
}
let nTotalCount: UINT; nTotalCount = edgeContext.Store.len() as u32;
if (nTotalCount == 0)
{
hr = S_OK; return hr;
}
assert!((nTotalCount >= 2) && (nTotalCount <= (UINT::MAX - 2)));
pInactiveArray = &mut inactiveArrayStack[..];
if (nTotalCount > (INACTIVE_LIST_NUMBER!() as u32 - 2))
{
pInactiveArrayAllocation = vec![Default::default(); nTotalCount as usize + 2];
pInactiveArray = &mut pInactiveArrayAllocation;
}
let nSubpixelYCurrent = InitializeInactiveArray(
edgeContext.Store,
pInactiveArray,
nTotalCount,
Ref::new(&edgeTail)
);
let mut nSubpixelYBottom = edgeContext.MaxY;
assert!(nSubpixelYBottom > 0);
pInactiveArray = &mut pInactiveArray[1..];
nSubpixelYBottom = nSubpixelYBottom.min(nPixelYClipBottom << c_nShift);
assert!(nSubpixelYBottom > nSubpixelYCurrent);
IFC!(self.RasterizeEdges(
pEdgeActiveList,
pInactiveArray,
&coverageBuffer,
nSubpixelYCurrent,
nSubpixelYBottom
));
return hr;
}
pub fn new(
pIGeometrySink: &'x mut CHwVertexBufferBuilder<'y, 'z>,
fillMode: MilFillMode,
pmatWorldToDevice: Option<CMatrix<CoordinateSpace::Shape,CoordinateSpace::Device>>,
clipRect: MilPointAndSizeL,
) -> Self
{
let mut matWorldHPCToDeviceIPC = pmatWorldToDevice.unwrap_or(CMatrix::Identity());
matWorldHPCToDeviceIPC.SetDx(matWorldHPCToDeviceIPC.GetDx() - 0.5);
matWorldHPCToDeviceIPC.SetDy(matWorldHPCToDeviceIPC.GetDy() - 0.5);
Self {
m_fillMode: fillMode,
m_rcClipBounds: clipRect,
m_pIGeometrySink: pIGeometrySink,
m_matWorldToDevice: matWorldHPCToDeviceIPC,
}
}
pub fn SendGeometry(&mut self,
points: &[POINT],
types: &[BYTE],
) -> HRESULT
{
let mut hr = S_OK;
let count = points.len() as u32;
IFR!(self.RasterizePath(
points,
types,
count,
&self.m_matWorldToDevice.clone(),
));
if (self.m_pIGeometrySink.IsEmpty())
{
hr = WGXHR_EMPTYFILL;
}
RRETURN1!(hr, WGXHR_EMPTYFILL);
}
fn
GenerateOutputAndClearCoverage<'a>(&mut self, coverageBuffer: &'a CCoverageBuffer<'a>,
nSubpixelY: INT
) -> HRESULT
{
let hr = S_OK;
let nPixelY = nSubpixelY >> c_nShift;
let pIntervalSpanStart: Ref<CCoverageInterval> = coverageBuffer.m_pIntervalStart.get();
IFC!(self.m_pIGeometrySink.AddComplexScan(nPixelY, pIntervalSpanStart));
coverageBuffer.Reset();
return hr;
}
fn ComputeTrapezoidsEndScan(&mut self,
pEdgeCurrent: Ref<CEdge>,
nSubpixelYCurrent: INT,
nSubpixelYNextInactive: INT
) -> INT
{
let mut nSubpixelYBottomTrapezoids;
let mut pEdgeLeft: Ref<CEdge>;
let mut pEdgeRight: Ref<CEdge>;
assert!((nSubpixelYCurrent & c_nShiftMask) == 0);
if (self.m_fillMode == MilFillMode::Winding)
{
let mut pEdge = pEdgeCurrent;
while pEdge.EndY != INT::MIN {
assert!(pEdge.Next.get().EndY != INT::MIN);
if (pEdge.WindingDirection == pEdge.Next.get().WindingDirection)
{
nSubpixelYBottomTrapezoids = nSubpixelYCurrent;
return nSubpixelYBottomTrapezoids;
}
pEdge = pEdge.Next.get().Next.get();
}
}
nSubpixelYBottomTrapezoids = nSubpixelYNextInactive;
let mut pEdge = pEdgeCurrent;
while pEdge.EndY != INT::MIN {
nSubpixelYBottomTrapezoids = nSubpixelYBottomTrapezoids.min(pEdge.EndY);
pEdgeLeft = pEdge;
pEdgeRight = pEdge.Next.get();
if (pEdgeRight.EndY != INT::MIN)
{
let nSubpixelExpandDistanceUpperBound: INT =
c_nShiftSize
+ ComputeDeltaUpperBound(&*pEdgeLeft, c_nHalfShiftSize)
+ ComputeDeltaUpperBound(&*pEdgeRight, c_nHalfShiftSize);
let nSubpixelXTopDistanceLowerBound: INT =
ComputeDistanceLowerBound(&*pEdgeLeft, &*pEdgeRight) - nSubpixelExpandDistanceUpperBound;
if (nSubpixelXTopDistanceLowerBound < 0)
{
nSubpixelYBottomTrapezoids = nSubpixelYCurrent;
return nSubpixelYBottomTrapezoids;
}
if (pEdgeLeft.Dx > pEdgeRight.Dx
|| ((pEdgeLeft.Dx == pEdgeRight.Dx)
&& IsFractionGreaterThan(pEdgeLeft.ErrorUp, pEdgeLeft.ErrorDown, pEdgeRight.ErrorUp, pEdgeRight.ErrorDown)))
{
let nSubpixelYAdvance: INT = nSubpixelYBottomTrapezoids - nSubpixelYCurrent;
assert!(nSubpixelYAdvance > 0);
let mut nSubpixelXLeftAdjustedBottom = 0;
let mut nSubpixelErrorLeftBottom = 0;
let mut nSubpixelXRightBottom = 0;
let mut nSubpixelErrorRightBottom = 0;
AdvanceDDAMultipleSteps(
&*pEdgeLeft,
&*pEdgeRight,
nSubpixelYAdvance,
&mut nSubpixelXLeftAdjustedBottom,
&mut nSubpixelErrorLeftBottom,
&mut nSubpixelXRightBottom,
&mut nSubpixelErrorRightBottom
);
nSubpixelXLeftAdjustedBottom += nSubpixelExpandDistanceUpperBound;
if (nSubpixelXLeftAdjustedBottom >= nSubpixelXRightBottom)
{
let nSubpixelXBottomDistanceUpperBound: INT = nSubpixelXLeftAdjustedBottom - nSubpixelXRightBottom + 1;
assert!(nSubpixelXTopDistanceLowerBound >= 0);
assert!(nSubpixelXBottomDistanceUpperBound > 0);
#[cfg(debug_assertions)]
let nDbgPreviousSubpixelXBottomTrapezoids: INT = nSubpixelYBottomTrapezoids;
nSubpixelYBottomTrapezoids =
nSubpixelYCurrent +
(nSubpixelYAdvance * nSubpixelXTopDistanceLowerBound) /
(nSubpixelXTopDistanceLowerBound + nSubpixelXBottomDistanceUpperBound);
#[cfg(debug_assertions)]
assert!(nDbgPreviousSubpixelXBottomTrapezoids >= nSubpixelYBottomTrapezoids);
if (nSubpixelYBottomTrapezoids < nSubpixelYCurrent + c_nShiftSize)
{
nSubpixelYBottomTrapezoids = nSubpixelYCurrent;
return nSubpixelYBottomTrapezoids;
}
}
}
}
pEdge = pEdge.Next.get();
}
nSubpixelYBottomTrapezoids = nSubpixelYBottomTrapezoids & (!c_nShiftMask);
assert!(nSubpixelYBottomTrapezoids >= nSubpixelYCurrent);
return nSubpixelYBottomTrapezoids;
}
fn
OutputTrapezoids(&mut self,
pEdgeCurrent: Ref<CEdge>,
nSubpixelYCurrent: INT, nSubpixelYNext: INT ) -> HRESULT
{
let hr = S_OK;
let nSubpixelYAdvance: INT;
let mut rSubpixelLeftErrorDown: f32;
let mut rSubpixelRightErrorDown: f32;
let mut rPixelXLeft: f32;
let mut rPixelXRight: f32;
let mut rSubpixelLeftInvSlope: f32;
let mut rSubpixelLeftAbsInvSlope: f32;
let mut rSubpixelRightInvSlope: f32;
let mut rSubpixelRightAbsInvSlope: f32;
let mut rPixelXLeftDelta: f32;
let mut rPixelXRightDelta: f32;
let mut pEdgeLeft = pEdgeCurrent;
let mut pEdgeRight = (*pEdgeCurrent).Next.get();
assert!((nSubpixelYCurrent & c_nShiftMask) == 0);
assert!(pEdgeLeft.EndY != INT::MIN);
assert!(pEdgeRight.EndY != INT::MIN);
nSubpixelYAdvance = nSubpixelYNext - nSubpixelYCurrent;
loop
{
let mut nSubpixelXLeftBottom: INT = 0;
let mut nSubpixelErrorLeftBottom: INT = 0;
let mut nSubpixelXRightBottom: INT = 0;
let mut nSubpixelErrorRightBottom: INT = 0;
AdvanceDDAMultipleSteps(
&*pEdgeLeft,
&*pEdgeRight,
nSubpixelYAdvance,
&mut nSubpixelXLeftBottom,
&mut nSubpixelErrorLeftBottom,
&mut nSubpixelXRightBottom,
&mut nSubpixelErrorRightBottom
);
assert!(nSubpixelXLeftBottom <= nSubpixelXRightBottom);
assert!(nSubpixelYAdvance > 0);
rSubpixelLeftErrorDown = pEdgeLeft.ErrorDown as f32;
rSubpixelRightErrorDown = pEdgeRight.ErrorDown as f32;
rPixelXLeft = ConvertSubpixelXToPixel(pEdgeLeft.X.get(), pEdgeLeft.Error.get(), rSubpixelLeftErrorDown);
rPixelXRight = ConvertSubpixelXToPixel(pEdgeRight.X.get(), pEdgeRight.Error.get(), rSubpixelRightErrorDown);
rSubpixelLeftInvSlope = pEdgeLeft.Dx as f32 + pEdgeLeft.ErrorUp as f32/rSubpixelLeftErrorDown;
rSubpixelLeftAbsInvSlope = rSubpixelLeftInvSlope.abs();
rSubpixelRightInvSlope = pEdgeRight.Dx as f32 + pEdgeRight.ErrorUp as f32/rSubpixelRightErrorDown;
rSubpixelRightAbsInvSlope = rSubpixelRightInvSlope.abs();
rPixelXLeftDelta = 0.5 + 0.5 * rSubpixelLeftAbsInvSlope;
rPixelXRightDelta = 0.5 + 0.5 * rSubpixelRightAbsInvSlope;
let rPixelYTop = ConvertSubpixelYToPixel(nSubpixelYCurrent);
let rPixelYBottom = ConvertSubpixelYToPixel(nSubpixelYNext);
let rPixelXBottomLeft = ConvertSubpixelXToPixel(
nSubpixelXLeftBottom,
nSubpixelErrorLeftBottom,
pEdgeLeft.ErrorDown as f32
);
let rPixelXBottomRight = ConvertSubpixelXToPixel(
nSubpixelXRightBottom,
nSubpixelErrorRightBottom,
pEdgeRight.ErrorDown as f32
);
IFC!(self.m_pIGeometrySink.AddTrapezoid(
rPixelYTop, rPixelXLeft, rPixelXRight, rPixelYBottom, rPixelXBottomLeft, rPixelXBottomRight, rPixelXLeftDelta, rPixelXRightDelta ));
pEdgeLeft.X.set(nSubpixelXLeftBottom);
pEdgeLeft.Error.set(nSubpixelErrorLeftBottom);
pEdgeRight.X.set(nSubpixelXRightBottom);
pEdgeRight.Error.set(nSubpixelErrorRightBottom);
if (pEdgeRight.Next.get().EndY == INT::MIN)
{
break;
}
pEdgeLeft = pEdgeRight.Next.get();
pEdgeRight = pEdgeLeft.Next.get();
}
return hr;
}
fn
RasterizeEdges<'a, 'b>(&mut self,
pEdgeActiveList: Ref<'a, CEdge<'a>>,
mut pInactiveEdgeArray: &'a mut [CInactiveEdge<'a>],
coverageBuffer: &'b CCoverageBuffer<'b>,
mut nSubpixelYCurrent: INT,
nSubpixelYBottom: INT
) -> HRESULT
{
let hr: HRESULT = S_OK;
let mut pEdgePrevious: Ref<CEdge>;
let mut pEdgeCurrent: Ref<CEdge>;
let mut nSubpixelYNextInactive: INT = 0;
let mut nSubpixelYNext: INT;
pInactiveEdgeArray = InsertNewEdges(
pEdgeActiveList,
nSubpixelYCurrent,
pInactiveEdgeArray,
&mut nSubpixelYNextInactive
);
while (nSubpixelYCurrent < nSubpixelYBottom)
{
ASSERTACTIVELIST!(pEdgeActiveList, nSubpixelYCurrent);
pEdgePrevious = pEdgeActiveList;
pEdgeCurrent = pEdgeActiveList.Next.get();
nSubpixelYNext = nSubpixelYCurrent;
if (!IsTagEnabled!(tagDisableTrapezoids)
&& (nSubpixelYCurrent & c_nShiftMask) == 0
&& pEdgeCurrent.EndY != INT::MIN
&& nSubpixelYNextInactive >= nSubpixelYCurrent + c_nShiftSize
)
{
assert!(pEdgeCurrent.Next.get().EndY != INT::MIN);
nSubpixelYNext = self.ComputeTrapezoidsEndScan(Ref::new(&*pEdgeCurrent), nSubpixelYCurrent, nSubpixelYNextInactive);
assert!(nSubpixelYNext >= nSubpixelYCurrent);
if (nSubpixelYNext >= nSubpixelYCurrent + c_nShiftSize)
{
IFC!(self.OutputTrapezoids(
pEdgeCurrent,
nSubpixelYCurrent,
nSubpixelYNext
));
}
}
if (nSubpixelYNext > nSubpixelYCurrent)
{
assert!(nSubpixelYNext - nSubpixelYCurrent >= c_nShiftSize);
nSubpixelYCurrent = nSubpixelYNext;
while (pEdgeCurrent.EndY != INT::MIN)
{
if (pEdgeCurrent.EndY <= nSubpixelYCurrent)
{
pEdgeCurrent = pEdgeCurrent.Next.get();
pEdgePrevious.Next.set(pEdgeCurrent);
}
else
{
pEdgePrevious = pEdgeCurrent;
pEdgeCurrent = pEdgeCurrent.Next.get();
}
}
}
else
{
if (pEdgeCurrent.EndY == INT::MIN)
{
nSubpixelYNext = nSubpixelYNextInactive;
}
else
{
nSubpixelYNext = nSubpixelYCurrent + 1;
if (self.m_fillMode == MilFillMode::Alternate)
{
IFC!(coverageBuffer.FillEdgesAlternating(pEdgeActiveList, nSubpixelYCurrent));
}
else
{
IFC!(coverageBuffer.FillEdgesWinding(pEdgeActiveList, nSubpixelYCurrent));
}
}
if (nSubpixelYNext > (nSubpixelYCurrent | c_nShiftMask))
{
IFC!(self.GenerateOutputAndClearCoverage(coverageBuffer, nSubpixelYCurrent));
}
nSubpixelYCurrent = nSubpixelYNext;
AdvanceDDAAndUpdateActiveEdgeList(nSubpixelYCurrent, pEdgeActiveList);
}
if (nSubpixelYCurrent == nSubpixelYNextInactive)
{
pInactiveEdgeArray = InsertNewEdges(
pEdgeActiveList,
nSubpixelYCurrent,
pInactiveEdgeArray,
&mut nSubpixelYNextInactive
);
}
}
if ((nSubpixelYCurrent & c_nShiftMask) != 0)
{
IFC!(self.GenerateOutputAndClearCoverage(coverageBuffer, nSubpixelYCurrent));
}
RRETURN!(hr);
}
}