bool CDirectWriteRenderer::DrawText( LPCWSTR pText, int Length, const RECT &Rect, CDirectWriteFont &Font, CDirectWriteBrush &Brush, unsigned int Flags) { if (pText == nullptr) return false; if (m_pRenderTarget == nullptr) return false; bool fOK = false; IDWriteTextFormat *pTextFormat = Font.GetTextFormat(); if (pTextFormat != nullptr) { ID2D1Brush *pBrush = Brush.GetBrush(); if (pBrush != nullptr) { pTextFormat->SetTextAlignment( (Flags & DRAW_TEXT_ALIGN_HORZ_CENTER) != 0 ? DWRITE_TEXT_ALIGNMENT_CENTER : (Flags & DRAW_TEXT_ALIGN_RIGHT) != 0 ? DWRITE_TEXT_ALIGNMENT_TRAILING : ((Flags & DRAW_TEXT_ALIGN_JUSTIFIED) != 0 && Util::OS::IsWindows8OrLater()) ? DWRITE_TEXT_ALIGNMENT_JUSTIFIED : DWRITE_TEXT_ALIGNMENT_LEADING); pTextFormat->SetParagraphAlignment( (Flags & DRAW_TEXT_ALIGN_VERT_CENTER) != 0 ? DWRITE_PARAGRAPH_ALIGNMENT_CENTER : (Flags & DRAW_TEXT_ALIGN_BOTTOM) != 0 ? DWRITE_PARAGRAPH_ALIGNMENT_FAR : DWRITE_PARAGRAPH_ALIGNMENT_NEAR); pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); DWRITE_TRIMMING Trimming = {DWRITE_TRIMMING_GRANULARITY_NONE, 0, 0}; pTextFormat->SetTrimming(&Trimming, nullptr); m_pRenderTarget->DrawText( pText, Length >= 0 ? Length : ::lstrlenW(pText), pTextFormat, D2DRectF(Rect), pBrush); fOK = true; pBrush->Release(); } pTextFormat->Release(); } return fOK; }
void DWriteContext::SetFont(const LOGFONTW &logFont) { SafeRelease(&mTextFormat); mLastHFont = NULL; HRESULT hr = SetLOGFONT(logFont, 0.f); if (SUCCEEDED(hr)) hr = mTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING); if (SUCCEEDED(hr)) hr = mTextFormat->SetParagraphAlignment( DWRITE_PARAGRAPH_ALIGNMENT_CENTER); if (SUCCEEDED(hr)) hr = mTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); }
IDWriteTextFormat* createTextFormat(IDWriteFactory1* writeFactory, const char* fontName, bool alignmentCenterX, bool alignmentCenterY) { IDWriteTextFormat* textFormat; // Create a DirectWrite text format object. DX::ThrowIfFailed( writeFactory->CreateTextFormat( Utils::convertStringToWString(fontName).c_str(),//Gabriola NULL, DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 64.f, L"en-US", // Locale &textFormat ) ); // Center the text horizontally and vertically. textFormat->SetTextAlignment(alignmentCenterX ? DWRITE_TEXT_ALIGNMENT_CENTER : DWRITE_TEXT_ALIGNMENT_LEADING); textFormat->SetParagraphAlignment(alignmentCenterY ? DWRITE_PARAGRAPH_ALIGNMENT_CENTER : DWRITE_PARAGRAPH_ALIGNMENT_NEAR); return textFormat; }
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; }
HRESULT SaveToImageFile(PlotData **data , unsigned int imageWidth, unsigned int imageHeight , float rangeX, float rangeY , float leftMargin, float bottomMargin , float xTick, float yTick) { HRESULT hr = S_OK; // // Create Factories // IWICImagingFactory *pWICFactory = NULL; ID2D1Factory *pD2DFactory = NULL; IDWriteFactory *pDWriteFactory = NULL; IWICBitmap *pWICBitmap = NULL; ID2D1RenderTarget *pRT = NULL; IDWriteTextFormat *pTextFormat = NULL; ID2D1SolidColorBrush *pSolidBrush = 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 // if (SUCCEEDED(hr)) { hr = pWICFactory->CreateBitmap( imageWidth, imageHeight, 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"Arial"; static const FLOAT sc_fontSize = 20; 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 // } if (SUCCEEDED(hr)) { hr = pRT->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black), &pSolidBrush ); } if (SUCCEEDED(hr)) { // // Render into the bitmap // pRT->BeginDraw(); pRT->Clear(D2D1::ColorF(D2D1::ColorF::White)); D2D1_SIZE_F rtSize = pRT->GetSize(); //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); float scaleX = (rtSize.width - leftMargin) / rangeX; float scaleY = (rtSize.height - bottomMargin) / rangeY; // // Reset back to the identity transform // pRT->DrawLine(D2D1::Point2F(leftMargin, 0.0f), D2D1::Point2F(leftMargin, rtSize.height - bottomMargin), pSolidBrush); pRT->DrawLine(D2D1::Point2F(leftMargin, rtSize.height - bottomMargin), D2D1::Point2F(rtSize.width, rtSize.height - bottomMargin), pSolidBrush); pSolidBrush->SetColor(D2D1::ColorF(D2D1::ColorF::LightGray, 0.4f)); size_t countTicks = rangeY / yTick; for(size_t tick = 1; tick <= countTicks; ++tick) { float y = rtSize.height - bottomMargin - static_cast<float>(tick) * yTick * scaleY; pRT->DrawLine(D2D1::Point2F(leftMargin - 3.0f, y), D2D1::Point2F(rtSize.width, y), pSolidBrush); } countTicks = rangeX / xTick; for(size_t tick = 1; tick <= countTicks; ++tick) { float x = leftMargin + static_cast<float>(tick) * xTick * scaleX; pRT->DrawLine(D2D1::Point2F(x, 0.0f), D2D1::Point2F(x, rtSize.height - bottomMargin + 3.0f), pSolidBrush); } //D2D1_MATRIX_3X2_F rotation = D2D1::Matrix3x2F::Rotation(-90.0f); D2D1_MATRIX_3X2_F translation = D2D1::Matrix3x2F::Translation(leftMargin, rtSize.height - bottomMargin); //D2D1_MATRIX_3X2_F scale = D2D1::Matrix3x2F::Scale(D2D1::SizeF(600.0f, 1.0f)); pRT->SetTransform(translation); GraphData(data, pD2DFactory, pRT, pSolidBrush, scaleX, scaleY ); 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(imageWidth, imageHeight); } 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(&pSolidBrush); SafeRelease(&pEncoder); SafeRelease(&pFrameEncode); SafeRelease(&pStream); 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; }