// Create device-independent resources HRESULT DemoApp::CreateDeviceIndependentResources() { static const WCHAR msc_fontName[] = L"Verdana"; static const FLOAT msc_fontSize = 50; HRESULT hr; ID2D1GeometrySink *pSink = NULL; // Create a Direct2D factory hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory); if (SUCCEEDED(hr)) { // Create WIC factory hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void **>(&m_pWICFactory)); } if (SUCCEEDED(hr)) { // Create a DirectWrite factory hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(m_pDWriteFactory), reinterpret_cast<IUnknown **>(&m_pDWriteFactory)); } if (SUCCEEDED(hr)) { // Create a DirectWrite text format object hr = m_pDWriteFactory->CreateTextFormat( msc_fontName, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, msc_fontSize, L"", &m_pTextFormat); } if (SUCCEEDED(hr)) { // center the text horizontally and vertically m_pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER); m_pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER); // Create a path geometry hr = m_pD2DFactory->CreatePathGeometry(&m_pPathGeometry); } if (SUCCEEDED(hr)) { // Use the geometry sink to write to the path geometry hr = m_pPathGeometry->Open(&pSink); } if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); pSink->BeginFigure(D2D1::Point2F(0, 0), D2D1_FIGURE_BEGIN_FILLED); pSink->AddLine(D2D1::Point2F(200, 0)); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(150, 50), D2D1::Point2F(150, 150), D2D1::Point2F(200, 200))); pSink->AddLine(D2D1::Point2F(0, 200)); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(50, 150), D2D1::Point2F(50, 50), D2D1::Point2F(0, 0))); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); hr = pSink->Close(); } SafeRelease(&pSink); return hr; }
HRESULT SaveToImageFile() { HRESULT hr = S_OK; // // Create Factories // IWICImagingFactory *pWICFactory = NULL; ID2D1Factory *pD2DFactory = NULL; IDWriteFactory *pDWriteFactory = NULL; IWICBitmap *pWICBitmap = NULL; ID2D1RenderTarget *pRT = NULL; IDWriteTextFormat *pTextFormat = NULL; ID2D1PathGeometry *pPathGeometry = NULL; ID2D1GeometrySink *pSink = NULL; ID2D1GradientStopCollection *pGradientStops = NULL; ID2D1LinearGradientBrush *pLGBrush = NULL; ID2D1SolidColorBrush *pBlackBrush = NULL; IWICBitmapEncoder *pEncoder = NULL; IWICBitmapFrameEncode *pFrameEncode = NULL; IWICStream *pStream = NULL; hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void **>(&pWICFactory) ); if (SUCCEEDED(hr)) { hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory); } if (SUCCEEDED(hr)) { hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(pDWriteFactory), reinterpret_cast<IUnknown **>(&pDWriteFactory) ); } // // Create IWICBitmap and RT // static const UINT sc_bitmapWidth = 640; static const UINT sc_bitmapHeight = 480; if (SUCCEEDED(hr)) { hr = pWICFactory->CreateBitmap( sc_bitmapWidth, sc_bitmapHeight, GUID_WICPixelFormat32bppBGR, WICBitmapCacheOnLoad, &pWICBitmap ); } if (SUCCEEDED(hr)) { hr = pD2DFactory->CreateWicBitmapRenderTarget( pWICBitmap, D2D1::RenderTargetProperties(), &pRT ); } if (SUCCEEDED(hr)) { // // Create text format // static const WCHAR sc_fontName[] = L"Calibri"; static const FLOAT sc_fontSize = 50; hr = pDWriteFactory->CreateTextFormat( sc_fontName, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, sc_fontSize, L"", //locale &pTextFormat ); } if (SUCCEEDED(hr)) { pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER); pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER); // // Create a path geometry representing an hour glass // hr = pD2DFactory->CreatePathGeometry(&pPathGeometry); } if (SUCCEEDED(hr)) { hr = pPathGeometry->Open(&pSink); } if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); pSink->BeginFigure( D2D1::Point2F(0, 0), D2D1_FIGURE_BEGIN_FILLED ); pSink->AddLine(D2D1::Point2F(200, 0)); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(150, 50), D2D1::Point2F(150, 150), D2D1::Point2F(200, 200)) ); pSink->AddLine(D2D1::Point2F(0, 200)); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(50, 150), D2D1::Point2F(50, 50), D2D1::Point2F(0, 0)) ); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); hr = pSink->Close(); } if (SUCCEEDED(hr)) { // // Create a linear-gradient brush // static const D2D1_GRADIENT_STOP stops[] = { { 0.f, { 0.f, 1.f, 1.f, 1.f } }, { 1.f, { 0.f, 0.f, 1.f, 1.f } }, }; hr = pRT->CreateGradientStopCollection( stops, ARRAYSIZE(stops), &pGradientStops ); } if (SUCCEEDED(hr)) { hr = pRT->CreateLinearGradientBrush( D2D1::LinearGradientBrushProperties( D2D1::Point2F(100, 0), D2D1::Point2F(100, 200)), D2D1::BrushProperties(), pGradientStops, &pLGBrush ); } if (SUCCEEDED(hr)) { hr = pRT->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black), &pBlackBrush ); } if (SUCCEEDED(hr)) { // // Render into the bitmap // pRT->BeginDraw(); pRT->Clear(D2D1::ColorF(D2D1::ColorF::White)); D2D1_SIZE_F rtSize = pRT->GetSize(); // Set the world transform to a 45 degree rotation at the center of the render target // and write "Hello, World". pRT->SetTransform( D2D1::Matrix3x2F::Rotation( 45, D2D1::Point2F( rtSize.width / 2, rtSize.height / 2)) ); static const WCHAR sc_helloWorld[] = L"Hello, World!"; pRT->DrawText( sc_helloWorld, ARRAYSIZE(sc_helloWorld) - 1, pTextFormat, D2D1::RectF(0, 0, rtSize.width, rtSize.height), pBlackBrush); // // Reset back to the identity transform // pRT->SetTransform(D2D1::Matrix3x2F::Translation(0, rtSize.height - 200)); pRT->FillGeometry(pPathGeometry, pLGBrush); pRT->SetTransform(D2D1::Matrix3x2F::Translation(rtSize.width - 200, 0)); pRT->FillGeometry(pPathGeometry, pLGBrush); hr = pRT->EndDraw(); } if (SUCCEEDED(hr)) { // // Save image to file // hr = pWICFactory->CreateStream(&pStream); } WICPixelFormatGUID format = GUID_WICPixelFormatDontCare; if (SUCCEEDED(hr)) { static const WCHAR filename[] = L"output.png"; hr = pStream->InitializeFromFilename(filename, GENERIC_WRITE); } if (SUCCEEDED(hr)) { hr = pWICFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &pEncoder); } if (SUCCEEDED(hr)) { hr = pEncoder->Initialize(pStream, WICBitmapEncoderNoCache); } if (SUCCEEDED(hr)) { hr = pEncoder->CreateNewFrame(&pFrameEncode, NULL); } if (SUCCEEDED(hr)) { hr = pFrameEncode->Initialize(NULL); } if (SUCCEEDED(hr)) { hr = pFrameEncode->SetSize(sc_bitmapWidth, sc_bitmapHeight); } if (SUCCEEDED(hr)) { hr = pFrameEncode->SetPixelFormat(&format); } if (SUCCEEDED(hr)) { hr = pFrameEncode->WriteSource(pWICBitmap, NULL); } if (SUCCEEDED(hr)) { hr = pFrameEncode->Commit(); } if (SUCCEEDED(hr)) { hr = pEncoder->Commit(); } SafeRelease(&pWICFactory); SafeRelease(&pD2DFactory); SafeRelease(&pDWriteFactory); SafeRelease(&pWICBitmap); SafeRelease(&pRT); SafeRelease(&pTextFormat); SafeRelease(&pPathGeometry); SafeRelease(&pSink); SafeRelease(&pGradientStops); SafeRelease(&pLGBrush); SafeRelease(&pBlackBrush); SafeRelease(&pEncoder); SafeRelease(&pFrameEncode); SafeRelease(&pStream); return hr; }
//----------------------------------------------------------------------------- ID2D1PathGeometry* D2DGraphicsPath::getPath (int32_t fillMode) { if (path == 0 || fillMode != currentPathFillMode) { dirty (); if (!SUCCEEDED (getD2DFactory ()->CreatePathGeometry (&path))) return 0; if (fillMode == -1) fillMode = 0; currentPathFillMode = fillMode; ID2D1GeometrySink* sink = 0; if (!SUCCEEDED (path->Open (&sink))) { path->Release (); path = 0; return 0; } sink->SetFillMode ((D2D1_FILL_MODE)fillMode); bool figureOpen = false; CPoint lastPos; for (ElementList::const_iterator it = elements.begin (); it != elements.end (); it++) { Element e = (*it); switch (e.type) { case Element::kArc: { bool clockwise = e.instruction.arc.clockwise; double startAngle = e.instruction.arc.startAngle; double endAngle = e.instruction.arc.endAngle; CRect o_r (e.instruction.arc.rect.left, e.instruction.arc.rect.top, e.instruction.arc.rect.right, e.instruction.arc.rect.bottom); CRect r (o_r); o_r.originize (); CPoint center = o_r.getCenter (); CPoint start; start.x = r.left + center.x + center.x * cos (radians (startAngle)); start.y = r.top + center.y + center.y * sin (radians (startAngle)); if (!figureOpen) { sink->BeginFigure (makeD2DPoint (start), D2D1_FIGURE_BEGIN_FILLED); figureOpen = true; } else if (lastPos != start) { sink->AddLine (makeD2DPoint (start)); } double sweepangle = endAngle - startAngle; if (clockwise) { // sweepangle positive while (sweepangle < 0.0) sweepangle += 360.0; while (sweepangle > 360.0) sweepangle -= 360.0; } else { // sweepangle negative while (sweepangle > 0.0) sweepangle -= 360.0; while (sweepangle < -360.0) sweepangle += 360.0; } CPoint endPoint; endPoint.x = r.left + center.x + center.x * cos (radians (endAngle)); endPoint.y = r.top + center.y + center.y * sin (radians (endAngle)); D2D1_ARC_SEGMENT arc; arc.size = makeD2DSize (r.getWidth ()/2., r.getHeight ()/2.); arc.rotationAngle = 0; arc.sweepDirection = clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE; arc.point = makeD2DPoint (endPoint); arc.arcSize = fabs(sweepangle) <= 180. ? D2D1_ARC_SIZE_SMALL : D2D1_ARC_SIZE_LARGE; sink->AddArc (arc); lastPos = endPoint; break; } case Element::kEllipse: { CRect r (e.instruction.rect.left, e.instruction.rect.top, e.instruction.rect.right, e.instruction.rect.bottom); CPoint top (r.getTopLeft ()); top.x += r.getWidth () / 2.; CPoint bottom (r.getBottomLeft ()); bottom.x += r.getWidth () / 2.; if (figureOpen && lastPos != CPoint (e.instruction.rect.left, e.instruction.rect.top)) { sink->EndFigure (D2D1_FIGURE_END_OPEN); figureOpen = false; } if (!figureOpen) { sink->BeginFigure (makeD2DPoint (top), D2D1_FIGURE_BEGIN_FILLED); figureOpen = true; } D2D1_ARC_SEGMENT arc = D2D1::ArcSegment (makeD2DPoint (bottom), D2D1::SizeF ((FLOAT)r.getWidth ()/2.f, (FLOAT)r.getHeight ()/2.f), 180.f, D2D1_SWEEP_DIRECTION_CLOCKWISE, D2D1_ARC_SIZE_SMALL); sink->AddArc (arc); arc.point = makeD2DPoint (top); sink->AddArc (arc); lastPos = top; break; } case Element::kRect: { D2D1_POINT_2F points[4] = { {(FLOAT)e.instruction.rect.right, (FLOAT)e.instruction.rect.top}, {(FLOAT)e.instruction.rect.right, (FLOAT)e.instruction.rect.bottom}, {(FLOAT)e.instruction.rect.left, (FLOAT)e.instruction.rect.bottom}, {(FLOAT)e.instruction.rect.left, (FLOAT)e.instruction.rect.top} }; if (figureOpen && lastPos != CPoint (e.instruction.rect.left, e.instruction.rect.top)) { sink->EndFigure (D2D1_FIGURE_END_OPEN); figureOpen = false; } if (figureOpen == false) { sink->BeginFigure (points[3], D2D1_FIGURE_BEGIN_FILLED); figureOpen = true; } sink->AddLine (points[0]); sink->AddLine (points[1]); sink->AddLine (points[2]); sink->AddLine (points[3]); lastPos = CPoint (e.instruction.rect.left, e.instruction.rect.top); break; } case Element::kLine: { if (figureOpen) { D2D1_POINT_2F end = {(FLOAT)e.instruction.point.x, (FLOAT)e.instruction.point.y}; sink->AddLine (end); lastPos = CPoint (e.instruction.point.x, e.instruction.point.y); } break; } case Element::kBezierCurve: { if (figureOpen) { D2D1_POINT_2F control1 = {(FLOAT)e.instruction.curve.control1.x, (FLOAT)e.instruction.curve.control1.y}; D2D1_POINT_2F control2 = {(FLOAT)e.instruction.curve.control2.x, (FLOAT)e.instruction.curve.control2.y}; D2D1_POINT_2F end = {(FLOAT)e.instruction.curve.end.x, (FLOAT)e.instruction.curve.end.y}; D2D1_BEZIER_SEGMENT bezier = D2D1::BezierSegment (control1, control2, end); sink->AddBezier (bezier); lastPos = CPoint (e.instruction.curve.end.x, e.instruction.curve.end.y); } break; } case Element::kBeginSubpath: { if (figureOpen) sink->EndFigure (D2D1_FIGURE_END_OPEN); D2D1_POINT_2F start = {(FLOAT)e.instruction.point.x, (FLOAT)e.instruction.point.y}; sink->BeginFigure (start, D2D1_FIGURE_BEGIN_FILLED); figureOpen = true; lastPos = CPoint (e.instruction.point.x, e.instruction.point.y); break; } case Element::kCloseSubpath: { if (figureOpen) { sink->EndFigure (D2D1_FIGURE_END_CLOSED); figureOpen = false; } break; } } } if (figureOpen) sink->EndFigure (D2D1_FIGURE_END_OPEN); HRESULT res = sink->Close (); if (!SUCCEEDED (res)) { path->Release (); path = 0; } sink->Release (); } return path; }
VOID CreateD2DResource(HWND hWnd) { // This function was called in the DrawRectangle function which in turn called to response the // WM_PAINT Message, to avoid creating resource every time, we test the pointer to g_pRenderTarget // If the resource already create, skip the function if (!g_pRenderTarget) { HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &g_pD2DFactory) ; if (FAILED(hr)) { MessageBox(hWnd, "Create D2D factory failed!", "Error", 0) ; return ; } // Obtain the size of the drawing area RECT rc ; GetClientRect(hWnd, &rc) ; // Create a Direct2D render target hr = g_pD2DFactory->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties( hWnd, D2D1::SizeU(rc.right - rc.left,rc.bottom - rc.top) ), &g_pRenderTarget ) ; if (FAILED(hr)) { MessageBox(hWnd, "Create render target failed!", "Error", 0) ; return ; } // Create a brush hr = g_pRenderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black), &g_pSceneBrush ) ; if (FAILED(hr)) { MessageBox(hWnd, "Create brush failed!", "Error", 0) ; return ; } // Create left mountain geometry hr = g_pD2DFactory->CreatePathGeometry(&g_pLeftMountainGeometry) ; if (SUCCEEDED(hr)) { ID2D1GeometrySink *pSink = NULL; hr = g_pLeftMountainGeometry->Open(&pSink); if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_WINDING); pSink->BeginFigure( D2D1::Point2F(346,255), D2D1_FIGURE_BEGIN_FILLED ); D2D1_POINT_2F points[5] = { D2D1::Point2F(267, 177), D2D1::Point2F(236, 192), D2D1::Point2F(212, 160), D2D1::Point2F(156, 255), D2D1::Point2F(346, 255), }; pSink->AddLines(points, ARRAYSIZE(points)); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); } pSink->Close() ; SAFE_RELEASE(pSink) ; } // Create right mountain geometry hr = g_pD2DFactory->CreatePathGeometry(&g_pRightMountainGeometry) ; if (SUCCEEDED(hr)) { ID2D1GeometrySink *pSink = NULL; hr = g_pRightMountainGeometry->Open(&pSink); if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_WINDING); pSink->BeginFigure( D2D1::Point2F(575,263), D2D1_FIGURE_BEGIN_FILLED ); D2D1_POINT_2F points[] = { D2D1::Point2F(481, 146), D2D1::Point2F(449, 181), D2D1::Point2F(433, 159), D2D1::Point2F(401, 214), D2D1::Point2F(381, 199), D2D1::Point2F(323, 263), D2D1::Point2F(575, 263) }; pSink->AddLines(points, ARRAYSIZE(points)); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); } hr = pSink->Close(); SAFE_RELEASE(pSink); } // Create sun geometry hr = g_pD2DFactory->CreatePathGeometry(&g_pSunGeometry) ; if (SUCCEEDED(hr)) { ID2D1GeometrySink *pSink = NULL; hr = g_pSunGeometry->Open(&pSink); if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_WINDING); pSink->BeginFigure( D2D1::Point2F(270, 255), D2D1_FIGURE_BEGIN_FILLED ); pSink->AddArc( D2D1::ArcSegment( D2D1::Point2F(440, 255), // end point D2D1::SizeF(85, 85), 0.0f, // rotation angle D2D1_SWEEP_DIRECTION_CLOCKWISE, D2D1_ARC_SIZE_SMALL )); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); pSink->BeginFigure( D2D1::Point2F(299, 182), D2D1_FIGURE_BEGIN_HOLLOW ); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(299, 182), D2D1::Point2F(294, 176), D2D1::Point2F(285, 178) )); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(276, 179), D2D1::Point2F(272, 173), D2D1::Point2F(272, 173) )); pSink->EndFigure(D2D1_FIGURE_END_OPEN); pSink->BeginFigure( D2D1::Point2F(354, 156), D2D1_FIGURE_BEGIN_HOLLOW ); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(354, 156), D2D1::Point2F(358, 149), D2D1::Point2F(354, 142) )); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(349, 134), D2D1::Point2F(354, 127), D2D1::Point2F(354, 127) )); pSink->EndFigure(D2D1_FIGURE_END_OPEN); pSink->BeginFigure( D2D1::Point2F(322,164), D2D1_FIGURE_BEGIN_HOLLOW ); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(322, 164), D2D1::Point2F(322, 156), D2D1::Point2F(314, 152) )); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(306, 149), D2D1::Point2F(305, 141), D2D1::Point2F(305, 141) )); pSink->EndFigure(D2D1_FIGURE_END_OPEN); pSink->BeginFigure( D2D1::Point2F(385, 164), D2D1_FIGURE_BEGIN_HOLLOW ); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(385,164), D2D1::Point2F(392,161), D2D1::Point2F(394,152) )); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(395,144), D2D1::Point2F(402,141), D2D1::Point2F(402,142) )); pSink->EndFigure(D2D1_FIGURE_END_OPEN); pSink->BeginFigure( D2D1::Point2F(408,182), D2D1_FIGURE_BEGIN_HOLLOW ); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(408,182), D2D1::Point2F(416,184), D2D1::Point2F(422,178) )); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(428,171), D2D1::Point2F(435,173), D2D1::Point2F(435,173) )); pSink->EndFigure(D2D1_FIGURE_END_OPEN); } hr = pSink->Close(); SAFE_RELEASE(pSink); } // Create river geometry hr = g_pD2DFactory->CreatePathGeometry(&g_pRiverGeometry) ; if (SUCCEEDED(hr)) { ID2D1GeometrySink *pSink = NULL; hr = g_pRiverGeometry->Open(&pSink); if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_WINDING); pSink->BeginFigure( D2D1::Point2F(183, 392), D2D1_FIGURE_BEGIN_FILLED ); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(238, 284), D2D1::Point2F(472, 345), D2D1::Point2F(356, 303) )); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(237, 261), D2D1::Point2F(333, 256), D2D1::Point2F(333, 256) )); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(335, 257), D2D1::Point2F(241, 261), D2D1::Point2F(411, 306) )); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(574, 350), D2D1::Point2F(288, 324), D2D1::Point2F(296, 392) )); pSink->EndFigure(D2D1_FIGURE_END_OPEN); } pSink->Close() ; SAFE_RELEASE(pSink) ; } } }
HRESULT DemoApp::CreateDeviceIndependentResources() { static const WCHAR msc_fontName[] = L"Verdana"; //사용할 폰트 이름 static const FLOAT msc_fontSize = 20; //폰트 크기 HRESULT hr = S_OK; ID2D1GeometrySink *pSink = NULL; // Create a Direct2D factory. hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory); if (SUCCEEDED(hr)) { // Create WIC factory. hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pWICFactory)); } if (SUCCEEDED(hr)) { // Create a DirectWrite factory. hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(m_pDWriteFactory), reinterpret_cast<IUnknown **>(&m_pDWriteFactory) ); } if (SUCCEEDED(hr)) { // Create a DirectWrite text format object. hr = m_pDWriteFactory->CreateTextFormat( msc_fontName, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, msc_fontSize, L"", //locale &m_pTextFormat ); } if (SUCCEEDED(hr)) // 바퀴벌레 기하 { hr = m_pD2DFactory->CreateEllipseGeometry(D2D1::Ellipse(D2D1::Point2F(0,0), 10, 5),&m_pWheel); } if (SUCCEEDED(hr)) // 칼날 반원 기하 { hr = m_pD2DFactory->CreatePathGeometry(&m_pPathGeometry); if (SUCCEEDED(hr)) { // Write to the path geometry using the geometry sink. hr = m_pPathGeometry->Open(&pSink); if (SUCCEEDED(hr)) { pSink->BeginFigure( D2D1::Point2F(200 , 100), // 200 ,100 D2D1_FIGURE_BEGIN_FILLED ); pSink->AddBezier(D2D1::BezierSegment( D2D1::Point2F(220, 300), D2D1::Point2F(380, -100) , D2D1::Point2F(400, 100) ) ); // 220, 300 380 -100 400 100 pSink->EndFigure(D2D1_FIGURE_END_CLOSED); hr = pSink->Close(); } SafeRelease(&pSink); } } if (SUCCEEDED(hr)) // 바퀴 경로 기하 { hr = m_pD2DFactory->CreatePathGeometry(&m_wheelPath); if (SUCCEEDED(hr)) { // Write to the path geometry using the geometry sink. hr = m_wheelPath->Open(&pSink); if (SUCCEEDED(hr)) { pSink->BeginFigure(D2D1::Point2F(200,0),D2D1_FIGURE_BEGIN_FILLED); pSink->AddBezier(D2D1::BezierSegment( D2D1::Point2F(250,-50),D2D1::Point2F(80,-80),D2D1::Point2F(0,-50))); pSink->AddBezier(D2D1::BezierSegment( D2D1::Point2F(-50,-10),D2D1::Point2F(-180,-80),D2D1::Point2F(-200,0))); pSink->AddBezier(D2D1::BezierSegment( D2D1::Point2F(-230,60),D2D1::Point2F(-80,70),D2D1::Point2F(0,50))); pSink->AddBezier(D2D1::BezierSegment( D2D1::Point2F(50,10),D2D1::Point2F(180,80),D2D1::Point2F(200,0))); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); hr = pSink->Close(); } SafeRelease(&pSink); } } if (SUCCEEDED(hr)) // 파리 경로 기하 { hr = m_pD2DFactory->CreatePathGeometry(&m_flyPath); if (SUCCEEDED(hr)) { // Write to the path geometry using the geometry sink. hr = m_flyPath->Open(&pSink); if (SUCCEEDED(hr)) { pSink->BeginFigure(D2D1::Point2F(200,0),D2D1_FIGURE_BEGIN_FILLED); pSink->AddBezier(D2D1::BezierSegment( D2D1::Point2F(250,-50),D2D1::Point2F(80,-80),D2D1::Point2F(-100,-50))); pSink->AddBezier(D2D1::BezierSegment( D2D1::Point2F(-50,-10),D2D1::Point2F(-180,-80),D2D1::Point2F(-100,0))); pSink->AddBezier(D2D1::BezierSegment( D2D1::Point2F(-230,60),D2D1::Point2F(-80,70),D2D1::Point2F(50,50))); pSink->AddBezier(D2D1::BezierSegment( D2D1::Point2F(50,10),D2D1::Point2F(180,80),D2D1::Point2F(300,60))); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); hr = pSink->Close(); } SafeRelease(&pSink); } } if(SUCCEEDED(hr)) //파리 몸통 기하 { hr = m_pD2DFactory->CreateEllipseGeometry( D2D1::Ellipse(D2D1::Point2F(0,0), 20, 10), &m_pFlyGeometry); } if(SUCCEEDED(hr)) //파리 오른쪽 눈알 기하 { hr = m_pD2DFactory->CreateEllipseGeometry( D2D1::Ellipse(D2D1::Point2F(20,-5), 5, 5), &m_pRightEyeGeometry); } if(SUCCEEDED(hr)) //파리 왼쪽 눈알 기하 { hr = m_pD2DFactory->CreateEllipseGeometry( D2D1::Ellipse(D2D1::Point2F(20,5), 5, 5), &m_pLeftEyeGeometry); } if(SUCCEEDED(hr)) //파리 날개 가운데 기하 { hr = m_pD2DFactory->CreatePathGeometry(&m_pMiddleWingGeometry); if(SUCCEEDED(hr)) { ID2D1GeometrySink *pSink = NULL; hr = m_pMiddleWingGeometry->Open(&pSink); if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_WINDING); pSink->BeginFigure( D2D1::Point2F(10, -9), D2D1_FIGURE_BEGIN_FILLED ); pSink->AddLine(D2D1::Point2F(10, -15)); pSink->AddArc(D2D1::ArcSegment(D2D1::Point2F(-10,-15),D2D1::SizeF(10,5),0, D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,D2D1_ARC_SIZE_SMALL)); pSink->AddLine(D2D1::Point2F(-10, -9)); pSink->AddLine(D2D1::Point2F(-10, 9)); pSink->AddLine(D2D1::Point2F(-10, 15)); pSink->AddArc(D2D1::ArcSegment(D2D1::Point2F(10,15),D2D1::SizeF(10,5),0, D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,D2D1_ARC_SIZE_SMALL)); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); } hr = pSink->Close(); SafeRelease(&pSink); } } if(SUCCEEDED(hr)) //파리 날개 위쪽 기하 { hr = m_pD2DFactory->CreatePathGeometry(&m_pUpWingGeometry); if(SUCCEEDED(hr)) { ID2D1GeometrySink *pSink = NULL; hr = m_pUpWingGeometry->Open(&pSink); if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_WINDING); pSink->BeginFigure( D2D1::Point2F(10, -9), D2D1_FIGURE_BEGIN_FILLED ); pSink->AddLine(D2D1::Point2F(10, -15)); pSink->AddArc(D2D1::ArcSegment(D2D1::Point2F(-10,-15),D2D1::SizeF(10,5),45, D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,D2D1_ARC_SIZE_SMALL)); pSink->AddLine(D2D1::Point2F(-10, -9)); pSink->AddLine(D2D1::Point2F(-10, 9)); pSink->AddLine(D2D1::Point2F(-10, 15)); pSink->AddArc(D2D1::ArcSegment(D2D1::Point2F(10,15),D2D1::SizeF(10,5),-45, D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,D2D1_ARC_SIZE_SMALL)); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); } hr = pSink->Close(); SafeRelease(&pSink); } } if(SUCCEEDED(hr)) //파리 날개 아래쪽 기하 { hr = m_pD2DFactory->CreatePathGeometry(&m_pDownWingGeometry); if(SUCCEEDED(hr)) { ID2D1GeometrySink *pSink = NULL; hr = m_pDownWingGeometry->Open(&pSink); if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_WINDING); pSink->BeginFigure( D2D1::Point2F(10, -9), D2D1_FIGURE_BEGIN_FILLED ); pSink->AddLine(D2D1::Point2F(10, -15)); pSink->AddArc(D2D1::ArcSegment(D2D1::Point2F(-10,-15),D2D1::SizeF(10,5),-45, D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,D2D1_ARC_SIZE_SMALL)); pSink->AddLine(D2D1::Point2F(-10, -9)); pSink->AddLine(D2D1::Point2F(-10, 9)); pSink->AddLine(D2D1::Point2F(-10, 15)); pSink->AddArc(D2D1::ArcSegment(D2D1::Point2F(10,15),D2D1::SizeF(10,5),45, D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,D2D1_ARC_SIZE_SMALL)); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); } hr = pSink->Close(); SafeRelease(&pSink); } } m_pWingGeometry[0] = m_pMiddleWingGeometry; //중간위치의 날개 m_pWingGeometry[1] = m_pUpWingGeometry; //위쪽 위치의 날개 m_pWingGeometry[2] = m_pMiddleWingGeometry; //중간위치의 날개 m_pWingGeometry[3] = m_pDownWingGeometry; //아래쪽 위치의 날개 return hr; }
int _tmain(int argc, _TCHAR* argv[]) { HRESULT hr = S_OK; // Create a Direct2D factory. CHECKHR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &g_pD2DFactory)); // Create a DirectWrite factory. CHECKHR(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&g_pDWriteFactory))); // Create a WIC factory IWICImagingFactory* pWICFactory = NULL; CHECKHR(CoInitialize(nullptr)); CHECKHR(CoCreateInstance(CLSID_WICImagingFactory1, nullptr, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pWICFactory)); // Create an IWICBitmap and RT IWICBitmap* pWICBitmap = NULL; static const UINT sc_bitmapWidth = 640; static const UINT sc_bitmapHeight = 480; CHECKHR(pWICFactory->CreateBitmap(sc_bitmapWidth, sc_bitmapHeight, GUID_WICPixelFormat32bppBGR, WICBitmapCacheOnLoad, &pWICBitmap)); // Set the render target type to D2D1_RENDER_TARGET_TYPE_DEFAULT to use software rendering. CHECKHR(g_pD2DFactory->CreateWicBitmapRenderTarget( pWICBitmap, D2D1::RenderTargetProperties(), &g_pRenderTarget)); // Create text format and a path geometry representing an hour glass. IDWriteTextFormat* pTextFormat = NULL; static const WCHAR sc_fontName[] = L"Calibri"; static const FLOAT sc_fontSize = 50; CHECKHR(g_pDWriteFactory->CreateTextFormat( sc_fontName, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, sc_fontSize, L"", //locale &pTextFormat )); CHECKHR(pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); CHECKHR(pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER)); // Create a path geometry ID2D1PathGeometry* pPathGeometry = NULL; ID2D1GeometrySink* pSink = NULL; CHECKHR(g_pD2DFactory->CreatePathGeometry(&pPathGeometry)); CHECKHR(pPathGeometry->Open(&pSink)); pSink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); pSink->BeginFigure( D2D1::Point2F(0, 0), D2D1_FIGURE_BEGIN_FILLED ); pSink->AddLine(D2D1::Point2F(200, 0)); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(150, 50), D2D1::Point2F(150, 150), D2D1::Point2F(200, 200)) ); pSink->AddLine(D2D1::Point2F(0, 200)); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(50, 150), D2D1::Point2F(50, 50), D2D1::Point2F(0, 0)) ); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); CHECKHR(pSink->Close()); // Create GradientStopCollection ID2D1GradientStopCollection *pGradientStops = NULL; static const D2D1_GRADIENT_STOP stops[] = { { 0.f, { 0.f, 1.f, 1.f, 1.f } }, { 1.f, { 0.f, 0.f, 1.f, 1.f } }, }; CHECKHR(g_pRenderTarget->CreateGradientStopCollection( stops, ARRAYSIZE(stops), &pGradientStops )); ID2D1LinearGradientBrush* pLGBrush = NULL; ID2D1SolidColorBrush* pBlackBrush = NULL; CHECKHR(g_pRenderTarget->CreateLinearGradientBrush( D2D1::LinearGradientBrushProperties( D2D1::Point2F(100, 0), D2D1::Point2F(100, 200)), D2D1::BrushProperties(), pGradientStops, &pLGBrush )); CHECKHR(g_pRenderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black), &pBlackBrush )); // Render into the bitmap. g_pRenderTarget->BeginDraw(); g_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White)); D2D1_SIZE_F rtSize = g_pRenderTarget->GetSize(); // Set the world transform to a 45 degree rotation at the center of the render target // and write "Hello, World". g_pRenderTarget->SetTransform( D2D1::Matrix3x2F::Rotation( 45, D2D1::Point2F( rtSize.width / 2, rtSize.height / 2)) ); static const WCHAR sc_helloWorld[] = L"Hello, World!"; g_pRenderTarget->DrawText( sc_helloWorld, ARRAYSIZE(sc_helloWorld) - 1, pTextFormat, D2D1::RectF(0, 0, rtSize.width, rtSize.height), pBlackBrush); // Reset back to the identity transform. g_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Translation(0, rtSize.height - 200)); g_pRenderTarget->FillGeometry(pPathGeometry, pLGBrush); g_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Translation(rtSize.width - 200, 0)); g_pRenderTarget->FillGeometry(pPathGeometry, pLGBrush); CHECKHR(g_pRenderTarget->EndDraw()); // Save the image to a file. IWICStream* pStream = NULL; CHECKHR(pWICFactory->CreateStream(&pStream)); // Use InitializeFromFilename to write to a file. If there is need to write inside the memory, use InitializeFromMemory. static const WCHAR filename[] = L"output.png"; CHECKHR(pStream->InitializeFromFilename(filename, GENERIC_WRITE)); IWICBitmapEncoder* pEncoder = NULL; CHECKHR(pWICFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &pEncoder)); CHECKHR(pEncoder->Initialize(pStream, WICBitmapEncoderNoCache)); IWICBitmapFrameEncode* pFrameEncode = NULL; CHECKHR(pEncoder->CreateNewFrame(&pFrameEncode, NULL)); // Use IWICBitmapFrameEncode to encode the bitmap into the picture format you want. CHECKHR(pFrameEncode->Initialize(NULL)); CHECKHR(pFrameEncode->SetSize(sc_bitmapWidth, sc_bitmapHeight)); WICPixelFormatGUID format = GUID_WICPixelFormatDontCare; CHECKHR(pFrameEncode->SetPixelFormat(&format)); CHECKHR(pFrameEncode->WriteSource(pWICBitmap, NULL)); CHECKHR(pFrameEncode->Commit()); CHECKHR(pEncoder->Commit()); return 0; }
HRESULT DemoApp::CreateGeometries() { HRESULT hr = S_OK; if (!m_pGeometry) { IGeometryRealizationFactory *pRealizationFactory = NULL; IGeometryRealization *pRealization = NULL; ID2D1TransformedGeometry *pGeometry = NULL; ID2D1PathGeometry *pPathGeometry = NULL; ID2D1GeometrySink *pSink = NULL; float squareWidth = 0.9f * sc_boardWidth / m_numSquares; // Create the path geometry. hr = m_pD2DFactory->CreatePathGeometry(&pPathGeometry); if (SUCCEEDED(hr)) { // Write to the path geometry using the geometry sink to // create an hour glass shape. hr = pPathGeometry->Open(&pSink); } if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); pSink->BeginFigure( D2D1::Point2F(0, 0), D2D1_FIGURE_BEGIN_FILLED ); pSink->AddLine(D2D1::Point2F(1.0f, 0)); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(0.75f, 0.25f), D2D1::Point2F(0.75f, 0.75f), D2D1::Point2F(1.0f, 1.0f)) ); pSink->AddLine(D2D1::Point2F(0, 1.0f)); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(0.25f, 0.75f), D2D1::Point2F(0.25f, 0.25f), D2D1::Point2F(0, 0)) ); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); hr = pSink->Close(); } if (SUCCEEDED(hr)) { D2D1_MATRIX_3X2_F scale = D2D1::Matrix3x2F::Scale(squareWidth, squareWidth); D2D1_MATRIX_3X2_F translation = D2D1::Matrix3x2F::Translation(-squareWidth / 2, -squareWidth / 2); hr = m_pD2DFactory->CreateTransformedGeometry( pPathGeometry, scale * translation, &pGeometry ); } if (SUCCEEDED(hr)) { // Transfer the reference. m_pGeometry = pGeometry; pGeometry = NULL; } SafeRelease(&pRealizationFactory); SafeRelease(&pRealization); SafeRelease(&pGeometry); SafeRelease(&pPathGeometry); SafeRelease(&pSink); } return hr; }