Esempio n. 1
0
/// <summary>
/// Initializes a new instance of the <see cref="Polyline"/> class.
/// </summary>
/// <param name="">The .</param>
RubyGM::Drawable::Polyline::Polyline(const PolylineStatus& ps) noexcept : 
Super(ps) {
    assert(m_pGiGeometry == nullptr);
    assert(ps.points && ps.count >= 2); 
    this->filled_color.a = 0.f;
    // 初始化
    ID2D1PathGeometry* path = nullptr;
    ID2D1GeometrySink* sink = nullptr;
    // 创建路径几何
    auto hr = Bridge::CreatePathGeometry(path);
    // 打开路径记录
    if (SUCCEEDED(hr)) {
        hr = path->Open(&sink);
    }
    // 填充路径
    if (SUCCEEDED(hr)) {
        auto points = impl::d2d(ps.points);
        sink->BeginFigure(*points, D2D1_FIGURE_BEGIN_HOLLOW);
        sink->AddLines(points + 1, ps.count - 1);
        sink->EndFigure(D2D1_FIGURE_END_CLOSED);
        hr = sink->Close();
    }
    // 错误代码
    if (FAILED(hr)) Game::SetLastErrorCode(hr);
    RubyGM::SafeRelease(sink);
    // 数据转换
    auto gi = static_cast<ID2D1Geometry*>(path);
    m_pGiGeometry = static_cast<IGMGeometry*>(gi);
}
ID2D1PathGeometry* Direct2DLowLevelGraphicsContext::pathToPathGeometry (const Path& path, const AffineTransform& transform)
{
    ID2D1PathGeometry* p = nullptr;
    Direct2DFactories::getInstance().d2dFactory->CreatePathGeometry (&p);

    ComSmartPtr <ID2D1GeometrySink> sink;
    HRESULT hr = p->Open (sink.resetAndGetPointerAddress());
    sink->SetFillMode (D2D1_FILL_MODE_WINDING); // xxx need to check Path::isUsingNonZeroWinding()

    pathToGeometrySink (path, sink, transform);

    hr = sink->Close();
    return p;
}
Esempio n. 3
0
void Renderer::FillPolygon(Vector2D * points, int size, bool close)
{
	if (size < 3)
		return;

	HRESULT hr;

	ID2D1PathGeometry* pGeometry = nullptr;
	hr = GRAPHICSDEVICEMANAGER->GetGraphics()->GetD2DFactory()->CreatePathGeometry(&pGeometry);
	if (FAILED(hr))
	{
		SafeRelease(pGeometry);
		//Logger::Log(_T("Failed to create path geometry"), LOGTYPE_WARNING, false);
		return;
	}

	//Write to the path geometry using the geometry sink
	ID2D1GeometrySink* pGeometrySink = nullptr;
	hr = pGeometry->Open(&pGeometrySink);
	if (FAILED(hr))
	{
		SafeRelease(pGeometrySink);
		SafeRelease(pGeometry);
		//Logger::Log(_T("Failed to create geometry sink"), LOGTYPE_WARNING, false);
		return;
	}

	if (SUCCEEDED(hr))
	{
		pGeometrySink->BeginFigure(D2D1::Point2((FLOAT)points[0].x, (FLOAT)points[0].y), D2D1_FIGURE_BEGIN_FILLED);

		for (int i = 1; i < size; ++i)
			pGeometrySink->AddLine(D2D1::Point2F((FLOAT)points[i].x, (FLOAT)points[i].y));

		pGeometrySink->EndFigure(D2D1_FIGURE_END_CLOSED);

		hr = pGeometrySink->Close();
		SafeRelease(pGeometrySink);
	}

	if (SUCCEEDED(hr))
	{
		GRAPHICSDEVICEMANAGER->GetGraphics()->GetRenderTarget()->FillGeometry(pGeometry, GRAPHICSDEVICEMANAGER->GetGraphics()->GetColorBrush());
		SafeRelease(pGeometry);
		return;
	}

	SafeRelease(pGeometry);
}
ID2D1PathGeometry* Direct2DLowLevelGraphicsContext::rectListToPathGeometry (const RectangleList& clipRegion)
{
    ID2D1PathGeometry* p = nullptr;
    Direct2DFactories::getInstance().d2dFactory->CreatePathGeometry (&p);

    ComSmartPtr <ID2D1GeometrySink> sink;
    HRESULT hr = p->Open (sink.resetAndGetPointerAddress()); // xxx handle error
    sink->SetFillMode (D2D1_FILL_MODE_WINDING);

    for (int i = clipRegion.getNumRectangles(); --i >= 0;)
        rectToGeometrySink (clipRegion.getRectangle(i), sink);

    hr = sink->Close();
    return p;
}
Esempio n. 5
0
 ~D2DPathRendererState() {
     if (path)
     {
         path->Release();
         path = NULL;
     }
 }
void VGraphicPath::Widen(const GReal inStrokeWidth, ID2D1StrokeStyle* inStrokeStyle)
{
	xbox_assert(inStrokeStyle);
	End();

	if (fPathD2D != NULL)
	{
		CComPtr<ID2D1StrokeStyle> strokeStyle = (ID2D1StrokeStyle *)inStrokeStyle;
		ID2D1Geometry *oldPath = fPathD2D;

		//create new path
		ID2D1PathGeometry *newPath = NULL;
		VWinD2DGraphicContext::GetMutexFactory().Lock();
		HRESULT hr = VWinD2DGraphicContext::GetFactory()->CreatePathGeometry( &newPath);
		xbox_assert(SUCCEEDED(hr));
		VWinD2DGraphicContext::GetMutexFactory().Unlock();

		//widen current path
		CComPtr<ID2D1GeometrySink> thisGeomSink;
		if (SUCCEEDED(newPath->Open(&thisGeomSink)))
		{
			thisGeomSink->SetFillMode( fFillMode == FILLRULE_EVENODD ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING);

			if (!SUCCEEDED(oldPath->Widen(
							inStrokeWidth,
							strokeStyle,
							NULL,
							0.0f,
							thisGeomSink)))
			{
				newPath->Release();
				return;
			}
			thisGeomSink->Close();
		}

		fPathD2D = newPath;
		oldPath->Release();

		fCreateStorageForCrispEdges = false;
		fHasBezier = false;
		fDrawCmds.clear();
		fCurTransform.MakeIdentity();
	}
}
void VGraphicPath::Begin()
{
#if ENABLE_D2D
	//start to populate geometry
	if (fGeomSink)
		return;
	if (fPathD2D == NULL)
		return;

	ID2D1PathGeometry *thisPath = NULL;
	if (FAILED(fPathD2D->QueryInterface( __uuidof(ID2D1PathGeometry), (void **)&thisPath)))
		return; //no more a ID2D1PathGeometry so skip
	ID2D1GeometrySink *thisGeomSink;
	if (SUCCEEDED(thisPath->Open(&thisGeomSink)))
	{
		fGeomSink = thisGeomSink;
		thisGeomSink->SetFillMode( fFillMode == FILLRULE_EVENODD ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING);
		fFigureIsClosed = true;
	}
	thisPath->Release();
#endif
}
Esempio n. 8
0
void GraphData(PlotData **data, ID2D1Factory *d2dFactory, ID2D1RenderTarget *target, ID2D1SolidColorBrush *brush, float xScale, float yScale)
{
	int c = 0;
	while(*data)
	{
		brush->SetColor(Colors[c++]);
	    ID2D1PathGeometry *path = NULL;
		if(SUCCEEDED(d2dFactory->CreatePathGeometry(&path)))
		{
			ID2D1GeometrySink *sink = NULL;
			if (SUCCEEDED(path->Open(&sink)))
			{
				PlotGraph(**data, sink, xScale, yScale);
				SUCCEEDED(sink->Close());
				target->DrawGeometry(path, brush);
				SafeRelease(&sink);
			}
			SafeRelease(&path);
		}
		data++;
	}
}
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;
}
Esempio n. 10
0
/** combine current path with the specified path
@remarks
	does not update internal polygon
	used only by D2D impl for path clipping implementation
*/
void VGraphicPath::_Combine( const VGraphicPath& inPath, bool inIntersect)
{
	End();

	//ensure proper combination if current path or input path is empty
	if (inPath.GetBounds().GetWidth() == 0.0f || inPath.GetBounds().GetHeight() == 0.0f)
	{
		//input path is empty
		if (inIntersect)
			Clear();
		return;
	}
	if (GetBounds().GetWidth() == 0.0f || GetBounds().GetHeight() == 0.0f)
	{
		//current path is empty
		if (inIntersect)
			return;
		else
			*this = inPath;
		return;
	}

	//combine D2D path if appropriate
	//TODO: make it work for Gdiplus::GraphicPath too ?
	if (fPathD2D != NULL && inPath.GetImplPathD2D())
	{
		ID2D1Geometry *oldPath = fPathD2D;

		//create new path
		ID2D1PathGeometry *newPath = NULL;
		VWinD2DGraphicContext::GetMutexFactory().Lock();
		HRESULT hr = VWinD2DGraphicContext::GetFactory()->CreatePathGeometry( &newPath);
		xbox_assert(SUCCEEDED(hr));
		VWinD2DGraphicContext::GetMutexFactory().Unlock();

		//combine current path with input path
		CComPtr<ID2D1GeometrySink> thisGeomSink;
		if (SUCCEEDED(newPath->Open(&thisGeomSink)))
		{
			thisGeomSink->SetFillMode( fFillMode == FILLRULE_EVENODD ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING);

			if (!SUCCEEDED(oldPath->CombineWithGeometry(
							inPath.GetImplPathD2D(),
							inIntersect ? D2D1_COMBINE_MODE_INTERSECT : D2D1_COMBINE_MODE_UNION,
							NULL,
							0.0f,
							thisGeomSink
							)))
			{
				newPath->Release();
				return;
			}
			thisGeomSink->Close();
		}

		fPathD2D = newPath;
		oldPath->Release();

		if (inIntersect)
			fBounds.Intersect( inPath.GetBounds());
		else
			fBounds.Union( inPath.GetBounds());

		fCreateStorageForCrispEdges = false;
		fHasBezier = false;
		fDrawCmds.clear();
		fCurTransform.MakeIdentity();
	}
}
//
// Generates new graph geometry, which may change every frame.
//
HRESULT D3D12MemoryManagement::GenerateMemoryGraphGeometry(const RectF& Bounds, UINT GraphSizeMB, ID2D1PathGeometry** ppPathGeometry)
{
    HRESULT hr;

    ID2D1PathGeometry* pPathGeometry = nullptr;
    ID2D1GeometrySink* pGeometrySink = nullptr;

    hr = m_pD2DFactory->CreatePathGeometry(&pPathGeometry);
    if (FAILED(hr))
    {
        LOG_WARNING("Failed to create path geometry, hr=0x%.8x");
        goto cleanup;
    }

    hr = pPathGeometry->Open(&pGeometrySink);
    if (FAILED(hr))
    {
        LOG_WARNING("Failed to open path geometry sink, hr=0x%.8x");
        goto cleanup;
    }

    {
        float GraphHeightPadded = GRAPH_HEIGHT * GRAPH_HEIGHT_RATIO / 100;
        float XStep = GRAPH_WIDTH / GRAPH_SEGMENTS;

        D2D1_POINT_2F Point;
        Point.x = Bounds.Left;
        Point.y = Bounds.Bottom;

        pGeometrySink->BeginFigure(Point, D2D1_FIGURE_BEGIN_FILLED);

        for (UINT i = 0; i < NUM_GRAPH_POINTS; ++i)
        {
            UINT32 GraphPoint = (i + m_CurrentGraphPoint) % NUM_GRAPH_POINTS;

            Point.y = Bounds.Bottom - (m_GraphPoints[GraphPoint] / 1024 / 1024) / (float)GraphSizeMB * GraphHeightPadded;
            pGeometrySink->AddLine(Point);
            Point.x += XStep;
        }

        Point.x = Bounds.Right;
        Point.y = Bounds.Bottom;
        pGeometrySink->AddLine(Point);

        pGeometrySink->EndFigure(D2D1_FIGURE_END_CLOSED);
    }

    hr = pGeometrySink->Close();
    if (FAILED(hr))
    {
        LOG_ERROR("Failed to close path geometry sink, hr=0x%.8x", hr);
        goto cleanup;
    }

    pGeometrySink->Release();
    *ppPathGeometry = pPathGeometry;

    return S_OK;

cleanup:
    SafeRelease(pGeometrySink);
    SafeRelease(pPathGeometry);

    return hr;
}
Esempio n. 12
0
/// <summary>
/// IDWriteTextRenderer::DrawGlyphRun
/// Draws glyphs
/// </summary>
HRESULT StateTextRender::DrawGlyphRun(
        LPVOID clientDrawingContext,
        FLOAT baselineOriginX,
        FLOAT baselineOriginY,
        DWRITE_MEASURING_MODE measuringMode,
        const DWRITE_GLYPH_RUN * glyphRun,
        const DWRITE_GLYPH_RUN_DESCRIPTION * glyphRunDescription,
        LPUNKNOWN clientDrawingEffect)
{
    UNREFERENCED_PARAMETER(glyphRunDescription);
    UNREFERENCED_PARAMETER(clientDrawingEffect);

    HRESULT hr = S_OK;

    auto renderTarget = ((ID2D1RenderTarget*) clientDrawingContext);

    // Since the fill looks horrid anyways, only do this if we are
    // going to stroke, and fill using D2D's DrawGlyphRun
    if (mState->mStateSettings.fontStrokeWidth > 0.0f)
    {
        // Get our D2D factory
        ID2D1Factory *d2dFactory;
        renderTarget->GetFactory(&d2dFactory);

        // Create the path geometry.
        ID2D1PathGeometry *pPathGeometry = nullptr;
        hr = d2dFactory->CreatePathGeometry(&pPathGeometry);

        // Write to the path geometry using the geometry sink.
        ID2D1GeometrySink* sink = nullptr;
        if (SUCCEEDED(hr))
        {
            hr = pPathGeometry->Open(&sink);
        }

        // Get the glyph run outline geometries back from DirectWrite and place them within the geometry sink.
        if (SUCCEEDED(hr))
        {
            hr = glyphRun->fontFace->GetGlyphRunOutline(
                glyphRun->fontEmSize,
                glyphRun->glyphIndices,
                glyphRun->glyphAdvances,
                glyphRun->glyphOffsets,
                glyphRun->glyphCount,
                glyphRun->isSideways,
                glyphRun->bidiLevel % 2,
                sink
            );
        }

        // Close the geometry sink
        if (SUCCEEDED(hr))
        {
            hr = sink->Close();
        }

        // Initialize a matrix to translate the origin of the glyph run.
        D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
            1.0f, 0.0f,
            0.0f, 1.0f,
            baselineOriginX, baselineOriginY
            );

        // Create the transformed geometry
        ID2D1TransformedGeometry* pTransformedGeometry = nullptr;
        if (SUCCEEDED(hr))
        {
            hr = d2dFactory->CreateTransformedGeometry(
                pPathGeometry,
                &matrix,
                &pTransformedGeometry
                );
        }

        ID2D1StrokeStyle* strokeStyle = nullptr;
        if (SUCCEEDED(hr))
        {
            d2dFactory->CreateStrokeStyle(
                D2D1::StrokeStyleProperties(
                    D2D1_CAP_STYLE_FLAT,
                    D2D1_CAP_STYLE_FLAT,
                    D2D1_CAP_STYLE_SQUARE,
                    D2D1_LINE_JOIN_BEVEL,
                    5.0f,
                    D2D1_DASH_STYLE_SOLID,
                    0.0f
                ),
                nullptr,
                0,
                &strokeStyle);
        }

        if (SUCCEEDED(hr))
        {

            float strokeWidth = mState->mStateSettings.fontStrokeWidth;
            if (strokeWidth != 0.0f)
            {
                // Draw the outline of the glyph run
                renderTarget->DrawGeometry(
                    pTransformedGeometry,
                    mState->mBrushes[State::BrushType::TextStroke].brush,
                    strokeWidth,
                    strokeStyle
                    );
            }

            // Fill in the glyph run
            // This is so ugly...
            /*renderTarget->FillGeometry(
                pTransformedGeometry,
                mState->mBrushes[State::BrushType::Text].brush
                );*/
        }
    
        SAFERELEASE(strokeStyle);
        SAFERELEASE(pPathGeometry);
        SAFERELEASE(sink);
        SAFERELEASE(pTransformedGeometry);
        d2dFactory->Release();
    }

    // TODO::Figure out how to replicate the quality of D2Ds DrawGlyphRun!
    renderTarget->DrawGlyphRun(D2D1::Point2F(baselineOriginX, baselineOriginY), glyphRun,
        mState->mBrushes[State::BrushType::Text].brush, measuringMode);

    return hr;
}
Esempio n. 13
0
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;
}