// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information.
//------------------------------------------------------------------------- // // TrapezoidalAA only supports 8x8 mode, so the shifts/masks are all // constants. Also, since we must be symmetrical, x and y shifts are // merged into one shift unlike the implementation in aarasterizer. // //-------------------------------------------------------------------------
pubconst c_nShift: INT = 3; pubconst c_nShiftSize: INT = 8; pubconst c_nShiftSizeSquared: INT = c_nShiftSize * c_nShiftSize; pubconst c_nHalfShiftSize: INT = 4; pubconst c_nShiftMask: INT = 7; //pub const c_rShiftSize: f32 = 8.0; //pub const c_rHalfShiftSize: f32 = 4.0; pubconst c_rInvShiftSize: f32 = 1.0/8.0; pubconst c_antiAliasMode: MilAntiAliasMode = MilAntiAliasMode::EightByEight;
// // Interval coverage descriptor for our antialiased filler //
pubstruct CCoverageInterval<'a>
{ pub m_pNext: Cell<Ref<'a, CCoverageInterval<'a>>>, // m_pNext interval (look for sentinel, not NULL) pub m_nPixelX: Cell<INT>, // Interval's left edge (m_pNext->X is the right edge) pub m_nCoverage: Cell<INT>, // Pixel coverage for interval
}
// Define our on-stack storage use. The 'free' versions are nicely tuned // to avoid allocations in most common scenarios, while at the same time // not chewing up toooo much stack space. // // We make the debug versions small so that we hit the 'grow' cases more // frequently, for better testing:
#[cfg(debug_assertions)] // Must be at least 6 now: 4 for the "minus4" logic in hwrasterizer.*, and then // 1 each for the head and tail sentinels (since their allocation doesn't use Grow). const INTERVAL_BUFFER_NUMBER: usize = 8; #[cfg(not(debug_assertions))] const INTERVAL_BUFFER_NUMBER: usize = 32;
// // Allocator structure for the antialiased fill interval data //
//------------------------------------------------------------------------------ // // Class: CCoverageBuffer // // Description: // Coverage buffer implementation that maintains coverage information // for one scanline. // // This implementation will maintain a linked list of intervals consisting // of x value in pixel space and a coverage value that applies for all pixels // between pInterval->X and pInterval->Next->X. // // For example, if we add the following interval (assuming 8x8 anti-aliasing) // to the coverage buffer: // _____ _____ _____ _____ // | | | | | // | ------------------- | // |_____|_____|_____|_____| // (0,0) (1,0) (2,0) (3,0) (4,0) // // Then we will get the following coverage buffer: // // m_nPixelX: INT_MIN | 0 | 1 | 3 | 4 | INT_MAX // m_nCoverage: 0 | 4 | 8 | 4 | 0 | 0xdeadbeef // m_pNext: -------->|---->|---->|---->|---->| NULL // //------------------------------------------------------------------------------ pubstruct CCoverageBuffer<'a>
{ /* public: // // Init/Destroy methods //
VOIDInitialize(); VOIDDestroy();
// // Setup the buffer so that it can accept another scanline //
VOIDReset();
// // Add a subpixel interval to the coverage buffer //
// The Minus4 in the below variable refers to the position at which // we need to Grow the buffer. The buffer is grown once before an // AddInterval, so the Grow has to ensure that there are enough // intervals for the AddInterval worst case which is the following: // // 1 2 3 4 // *_____*_____ _____*_____* // | | | | | // | ---|-----------|--- | // |_____|_____|_____|_____| // // Note that the *'s above mark potentional insert points in the list, // so we need to ensure that at least 4 intervals can be allocated. //
// // Inlines // impl<'a> CCoverageBuffer<'a> { //------------------------------------------------------------------------- // // Function: CCoverageBuffer::AddInterval // // Synopsis: Add a subpixel resolution interval to the coverage buffer // //------------------------------------------------------------------------- pubfn AddInterval(&'a self, nSubpixelXLeft: INT, nSubpixelXRight: INT) -> HRESULT
{ let hr: HRESULT = S_OK; letmut nPixelXNext: INT; let nPixelXLeft: INT; let nPixelXRight: INT; let nCoverageLeft: INT; // coverage from right edge of pixel for interval start let nCoverageRight: INT; // coverage from left edge of pixel for interval end
// Try to resume searching from the last searched interval. ifself.m_pIntervalLast.get().m_nPixelX.get() < nPixelXLeft {
pInterval = self.m_pIntervalLast.get();
}
// Skip any intervals less than 'nPixelLeft':
loop { let nextInterval = pInterval.m_pNext.get();
nPixelXNext = nextInterval.m_nPixelX.get(); if !(nPixelXNext < nPixelXLeft) { break }
pInterval = nextInterval;
}
// Remember the found interval. self.m_pIntervalLast.set(pInterval);
// Insert a new interval if necessary:
if (nPixelXNext != nPixelXLeft)
{
pIntervalNew.m_nPixelX.set(nPixelXLeft);
pIntervalNew.m_nCoverage.set(pInterval.m_nCoverage.get());
//Cleanup: // Update the coverage buffer new interval self.interval_new_index.set(interval_new_index); self.m_pIntervalNew.set(pIntervalNew);
return hr;
}
//------------------------------------------------------------------------- // // Function: CCoverageBuffer::FillEdgesAlternating // // Synopsis: // Given the active edge list for the current scan, do an alternate-mode // antialiased fill. // //------------------------------------------------------------------------- pubfn FillEdgesAlternating(&'a self,
pEdgeActiveList: Ref<CEdge>,
nSubpixelYCurrent: INT
) -> HRESULT
{
while (pEdgeStart.X.get() != INT::MAX)
{
pEdgeEnd = pEdgeStart.Next.get();
// We skip empty pairs:
(nSubpixelXLeft = pEdgeStart.X.get()); if (nSubpixelXLeft != pEdgeEnd.X.get())
{ // We now know we have a non-empty interval. Skip any // empty interior pairs:
// Prepare for the next iteration:
pEdgeStart = pEdgeEnd.Next.get();
}
//Cleanup: return hr
}
//------------------------------------------------------------------------- // // Function: CCoverageBuffer::FillEdgesWinding // // Synopsis: // Given the active edge list for the current scan, do an alternate-mode // antialiased fill. // //------------------------------------------------------------------------- pubfn FillEdgesWinding(&'a self,
pEdgeActiveList: Ref<CEdge>,
nSubpixelYCurrent: INT
) -> HRESULT
{
if ({nSubpixelXLeft = pEdgeStart.X.get(); nSubpixelXLeft != pEdgeEnd.X.get()})
{ // We now know we have a non-empty interval. Skip any // empty interior pairs:
//------------------------------------------------------------------------- // // Function: CCoverageBuffer::Destroy // // Synopsis: Free all allocated buffers // //------------------------------------------------------------------------- pubfn Destroy(&mutself)
{ // Free the linked-list of allocations (skipping 'm_pIntervalBufferBuiltin', // which is built into the class):
}
//------------------------------------------------------------------------- // // Function: CCoverageBuffer::Reset // // Synopsis: Reset the coverage buffer // //------------------------------------------------------------------------- pubfn Reset(&'a self)
{ // Reset our coverage structure. Point the head back to the tail, // and reset where the next new entry will be placed:
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.