void addAttributedRange (const AttributedString::Attribute& attr, IDWriteTextLayout& textLayout, const int textLen, ID2D1RenderTarget& renderTarget, IDWriteFontCollection& fontCollection) { DWRITE_TEXT_RANGE range; range.startPosition = attr.range.getStart(); range.length = jmin (attr.range.getLength(), textLen - attr.range.getStart()); if (const Font* const font = attr.getFont()) { const String familyName (FontStyleHelpers::getConcreteFamilyName (*font)); BOOL fontFound = false; uint32 fontIndex; fontCollection.FindFamilyName (familyName.toWideCharPointer(), &fontIndex, &fontFound); if (! fontFound) fontIndex = 0; ComSmartPtr<IDWriteFontFamily> fontFamily; HRESULT hr = fontCollection.GetFontFamily (fontIndex, fontFamily.resetAndGetPointerAddress()); ComSmartPtr<IDWriteFont> dwFont; uint32 fontFacesCount = 0; fontFacesCount = fontFamily->GetFontCount(); for (int i = fontFacesCount; --i >= 0;) { hr = fontFamily->GetFont (i, dwFont.resetAndGetPointerAddress()); if (font->getTypefaceStyle() == getFontFaceName (dwFont)) break; } textLayout.SetFontFamilyName (familyName.toWideCharPointer(), range); textLayout.SetFontWeight (dwFont->GetWeight(), range); textLayout.SetFontStretch (dwFont->GetStretch(), range); textLayout.SetFontStyle (dwFont->GetStyle(), range); const float fontHeightToEmSizeFactor = getFontHeightToEmSizeFactor (*dwFont); textLayout.SetFontSize (font->getHeight() * fontHeightToEmSizeFactor, range); } if (const Colour* const colour = attr.getColour()) { ComSmartPtr<ID2D1SolidColorBrush> d2dBrush; renderTarget.CreateSolidColorBrush (D2D1::ColorF (colour->getFloatRed(), colour->getFloatGreen(), colour->getFloatBlue(), colour->getFloatAlpha()), d2dBrush.resetAndGetPointerAddress()); // We need to call SetDrawingEffect with a legimate brush to get DirectWrite to break text based on colours textLayout.SetDrawingEffect (d2dBrush, range); } }
bool CDirectWriteBrush::Create(CDirectWriteRenderer &Renderer, BYTE Red, BYTE Green, BYTE Blue, BYTE Alpha) { Destroy(); ID2D1RenderTarget *pRenderTarget = Renderer.GetRenderTarget(); if (pRenderTarget == nullptr) return false; ID2D1SolidColorBrush *pBrush; HRESULT hr = pRenderTarget->CreateSolidColorBrush( D2DColorF(Red, Green, Blue, Alpha), &pBrush); if (SUCCEEDED(hr)) m_pBrush = pBrush; pRenderTarget->Release(); return true; }
void LetterHunter::drawBackgroundImage(wchar_t* imageFile) { static ID2D1Bitmap* pBitmap = NULL; ID2D1RenderTarget* renderTarget = d2d_->getD2DHwndRenderTarget(); static bool isImageLoad = false; if(!isImageLoad) { // Create WIC factory IWICImagingFactory* pWICFactory = NULL ; HRESULT hr = CoCreateInstance( CLSID_WICImagingFactory1, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void **>(&pWICFactory) ) ; d2d_->LoadBitmapFromFile( renderTarget, pWICFactory, imageFile, 0, 0, &pBitmap ); isImageLoad = true; } RECT rect; GetWindowRect(hwnd_, &rect); renderTarget->DrawBitmap( pBitmap, D2D1::Rect(rect.left, rect.top, rect.right, rect.bottom) ); }
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; }
void ImageWindow::AssociateSurface( void* surface ) { if (pD2DFactory) { // Assume an IUnknown IUnknown* unknown = (IUnknown*)surface; IDXGISurface *pDxgiSurface = NULL; HRESULT hr = unknown->QueryInterface(&pDxgiSurface); if( hr == S_OK ) { D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED), 96, 96 ); pRT = NULL; ID2D1RenderTarget* tmpTarget; hr = pD2DFactory->CreateDxgiSurfaceRenderTarget( pDxgiSurface, &props, &tmpTarget ); if( hr == S_OK ) { DXGI_SURFACE_DESC desc = {0}; pDxgiSurface->GetDesc( &desc ); int width = desc.Width; int height = desc.Height; D2D1_SIZE_U size = D2D1::SizeU( width, height ); D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat( DXGI_FORMAT_A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED ); D2D1_PIXEL_FORMAT colorPixelFormat = D2D1::PixelFormat( DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED ); D2D1_BITMAP_PROPERTIES bitmapProps; bitmapProps.dpiX = 96; bitmapProps.dpiY = 96; bitmapProps.pixelFormat = pixelFormat; D2D1_BITMAP_PROPERTIES colorBitmapProps; colorBitmapProps.dpiX = 96; colorBitmapProps.dpiY = 96; colorBitmapProps.pixelFormat = colorPixelFormat; HRESULT result = tmpTarget->CreateBitmap( size, bitmapProps, &greyBitmap ); if( result != S_OK ) { tmpTarget->Release(); tmpTarget = NULL; } if (tmpTarget) { result = tmpTarget->CreateBitmap(size, colorBitmapProps, &colorBitmap); if (result != S_OK) { tmpTarget->Release(); tmpTarget = NULL; } } pRT = tmpTarget; } } } }
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; }
static void d2d_blit(int x, int y, int y1, int y2, int w, int h) { HRESULT hr = S_OK; void *srcdata; int yy; D2D1_RECT_U rectU; ID2D1Bitmap *fs_bitmap; ID2D1RenderTarget *RT; float fs_x, fs_y; float fs_w = w; float fs_h = h; d2d_log("Direct2D: d2d_blit(x=%d, y=%d, y1=%d, y2=%d, w=%d, h=%d)\n", x, y, y1, y2, w, h); // TODO: Detect double scanned mode and resize render target // appropriately for more clear picture if (w != d2d_width || h != d2d_height) { if (d2d_fs) { if (d2d_btmpRT) { d2d_btmpRT->Release(); d2d_btmpRT = NULL; } hr = d2d_hwndRT->CreateCompatibleRenderTarget( D2D1::SizeF(w, h), &d2d_btmpRT); if (SUCCEEDED(hr)) { d2d_width = w; d2d_height = h; } } else { hr = d2d_hwndRT->Resize(D2D1::SizeU(w, h)); if (SUCCEEDED(hr)) { d2d_width = w; d2d_height = h; } } } if (y1 == y2) { video_blit_complete(); return; } if (buffer32 == NULL) { video_blit_complete(); return; } // TODO: Copy data directly from buffer32 to d2d_bitmap srcdata = malloc(h * w * 4); for (yy = y1; yy < y2; yy++) { if ((y + yy) >= 0 && (y + yy) < buffer32->h) { if (video_grayscale || invert_display) video_transform_copy( (uint32_t *) &(((uint8_t *)srcdata)[yy * w * 4]), &(((uint32_t *)buffer32->line[y + yy])[x]), w); else memcpy( (uint32_t *) &(((uint8_t *)srcdata)[yy * w * 4]), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); } } video_blit_complete(); rectU = D2D1::RectU(0, 0, w, h); hr = d2d_bitmap->CopyFromMemory(&rectU, srcdata, w * 4); // In fullscreen mode we first draw offscreen to an intermediate // BitmapRenderTarget, which then gets rendered to the actual // HwndRenderTarget in order to implement different scaling modes // In windowed mode we draw directly to the HwndRenderTarget if (SUCCEEDED(hr)) { RT = d2d_fs ? (ID2D1RenderTarget *) d2d_btmpRT : (ID2D1RenderTarget *) d2d_hwndRT; RT->BeginDraw(); RT->DrawBitmap( d2d_bitmap, D2D1::RectF(0, y1, w, y2), 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1::RectF(0, y1, w, y2)); hr = RT->EndDraw(); } if (d2d_fs) { if (SUCCEEDED(hr)) { hr = d2d_btmpRT->GetBitmap(&fs_bitmap); } if (SUCCEEDED(hr)) { d2d_stretch(&fs_w, &fs_h, &fs_x, &fs_y); d2d_hwndRT->BeginDraw(); d2d_hwndRT->Clear( D2D1::ColorF(D2D1::ColorF::Black)); d2d_hwndRT->DrawBitmap( fs_bitmap, D2D1::RectF(fs_x, fs_y, fs_x + fs_w, fs_y + fs_h), 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, D2D1::RectF(0, 0, w, h)); hr = d2d_hwndRT->EndDraw(); } } if (FAILED(hr)) { d2d_log("Direct2D: d2d_blit: error 0x%08lx\n", hr); } // Tidy up free(srcdata); srcdata = NULL; }
void drawToD2DContext (const AttributedString& text, const Rectangle<float>& area, ID2D1RenderTarget& renderTarget, IDWriteFactory& directWriteFactory, IDWriteFontCollection& fontCollection) { ComSmartPtr<IDWriteTextLayout> dwTextLayout; if (setupLayout (text, area.getWidth(), area.getHeight(), renderTarget, directWriteFactory, fontCollection, dwTextLayout)) { ComSmartPtr<ID2D1SolidColorBrush> d2dBrush; renderTarget.CreateSolidColorBrush (D2D1::ColorF (0.0f, 0.0f, 0.0f, 1.0f), d2dBrush.resetAndGetPointerAddress()); renderTarget.DrawTextLayout (D2D1::Point2F ((float) area.getX(), (float) area.getY()), dwTextLayout, d2dBrush, D2D1_DRAW_TEXT_OPTIONS_CLIP); } }