如何擴充 ID2D1SimplifiedGeometrySink 來擷取幾何資料
雖然 ID2D1Geometry 物件是不可變的,但在某些情況下,您需要操作路徑 geometry 物件中的幾何資料。 Direct2D 可讓您藉由提供名為 ID2D1SimplifiedGeometrySink的可延伸介面來執行這項操作。 如需概念圖例,本主題說明如何擴充此介面,以從路徑 geometry 物件擷取幾何資料。
擴充 ID2D1SimplifiedGeometrySink 介面
- 實作繼承自 ID2D1SimplifiedGeometrySink 的類別。
- 建立該類別的實例,並將它傳遞至 ID2D1Geometry::Simplify。
下列程式碼範例示範如何實作名為 SpecializedSink 的類別,該類別繼承自 ID2D1SimplifiedGeometrySink 介面。 為了簡單起見概念圖例,擴充 的 AddLines 方法會擷取幾何資料,然後在主控台視窗上顯示它;您可以自訂這個方法,以符合您的特定資料需求。
class SpecializedSink : public ID2D1SimplifiedGeometrySink
{
public:
SpecializedSink()
: m_cRef(1)
{
}
STDMETHOD_(ULONG, AddRef)(THIS)
{
return InterlockedIncrement(reinterpret_cast<LONG volatile *>(&m_cRef));
}
STDMETHOD_(ULONG, Release)(THIS)
{
ULONG cRef = static_cast<ULONG>(
InterlockedDecrement(reinterpret_cast<LONG volatile *>(&m_cRef)));
if(0 == cRef)
{
delete this;
}
return cRef;
}
STDMETHOD(QueryInterface)(THIS_ REFIID iid, void** ppvObject)
{
HRESULT hr = S_OK;
if (__uuidof(IUnknown) == iid)
{
*ppvObject = static_cast<IUnknown*>(this);
AddRef();
}
else if (__uuidof(ID2D1SimplifiedGeometrySink) == iid)
{
*ppvObject = static_cast<ID2D1SimplifiedGeometrySink*>(this);
AddRef();
}
else
{
*ppvObject = NULL;
hr = E_NOINTERFACE;
}
return hr;
}
STDMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT * /*beziers*/,
UINT /*beziersCount*/)
{
// Customize this method to meet your specific data needs.
}
STDMETHOD_(void, AddLines)(const D2D1_POINT_2F *points, UINT pointsCount)
{
// Customize this method to meet your specific data needs.
printf("\n\nRetrieving geometry data from a derived ID2D1SimplifiedGeometrySink object:\n");
for (UINT i = 0; i < pointsCount; ++i)
{
printf("%.0f, %.0f\n", points[i].x, points[i].y);
}
}
STDMETHOD_(void, BeginFigure)(D2D1_POINT_2F startPoint,
D2D1_FIGURE_BEGIN figureBegin)
{
}
STDMETHOD_(void, EndFigure)(D2D1_FIGURE_END figureEnd)
{
}
STDMETHOD_(void, SetFillMode)(D2D1_FILL_MODE fillMode)
{
}
STDMETHOD_(void, SetSegmentFlags)(D2D1_PATH_SEGMENT vertexFlags)
{
}
STDMETHOD(Close)()
{
return S_OK;
}
private:
UINT m_cRef;
};
此範例接著會使用一組資料 (182, 209) 、 (211、251) 、 (251、226) 、 (392、360) 和 (101、360) ,以建立可擷取資料的填入路徑幾何 (m_pGeometry) 。
hr = m_pD2DFactory->CreatePathGeometry(&m_pGeometry);
if(SUCCEEDED(hr))
{
ID2D1GeometrySink *pSink = NULL;
hr = m_pGeometry->Open(&pSink);
if (SUCCEEDED(hr))
{
pSink->SetFillMode(D2D1_FILL_MODE_WINDING);
pSink->BeginFigure(
D2D1::Point2F(101,360),
D2D1_FIGURE_BEGIN_FILLED
);
D2D1_POINT_2F points[5] = {
D2D1::Point2F(182,209),
D2D1::Point2F(211,251),
D2D1::Point2F(251,226),
D2D1::Point2F(392,360),
D2D1::Point2F(101,360),
};
printf("Adding the following geometry data to an ID2D1GeometrySink object:\n");
printf("182, 209\n");
printf("211, 251\n");
printf("251, 226\n");
printf("392, 360\n");
printf("101, 360\n");
pSink->AddLines(points, ARRAYSIZE(points));
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
hr = pSink->Close();
pSink->Release();
最後,此範例會建立 SpecializedSink 物件,然後呼叫 ID2D1Geometry::Simplify 方法,傳入 SpecializedSink 物件和 D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES 參數,這會導致任何曲線扁平化成線條線段。
SpecializedSink *pSpecializedSink = NULL;
if (SUCCEEDED(hr))
{
pSpecializedSink = new SpecializedSink();
if (!pSpecializedSink)
{
hr = E_OUTOFMEMORY;
}
}
if (SUCCEEDED(hr))
{
hr = m_pGeometry->Simplify(
D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES, // This causes any curves to be flattened into line segments.
NULL, // world transform
pSpecializedSink
);
if (SUCCEEDED(hr))
{
hr = pSpecializedSink->Close();
}
pSpecializedSink->Release();
}
程式會建立輸出,如下列螢幕擷取畫面所示。
相關主題