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);
        }
    }
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
		    }
	    }
    }
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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);
        }
    }