One of my personal goals is to celebrate several successes every day – even if these successes are fairly small. Today, I succeeded in using the Direct2D and DirectWrite libraries from .Net! It took several hours, of course, but I managed to my .Net code to lock a bitmap and manipulate it in unmanaged C++ code, actually writing some text to the bitmap.
Here’s how it goes. First, you need a System.Drawing.Bitmap created on the .Net side. You lock its bits, then send it over to the unmanaged (‘native’) function:
private static Size RegenerateFreeformImage(ConversionOptions options, string markup, int index)
{
const int w = 512, h = 256;
using (Bitmap bmp = new Bitmap(w, h))
{
BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite,
bmp.PixelFormat);
NativeMethods.RenderMarkup(data.Scan0, markup, data.Width, data.Height,
data.Stride, options.FreeformFontFamily, options.FreeformFontSize);
bmp.UnlockBits(data);
string filename = Path.Combine(Path.GetTempPath(), options.FreeformPrefix + index + ".jpg");
using (Bitmap bmp2 = FlowBasedRenderer.Crop(bmp))
SaveImageAsJpeg(bmp2, filename);
}
return new Size(w, h);
}
The C++ code picks up on this with the following (rather basic) signature:
MYAPI void RenderMarkup(BYTE* dst, LPCWSTR markup, int width, int height,
int stride, LPCWSTR fontFamily, float fontSize)
{
⋮
}
Inside, all operations happen on a separate bitmap object that we create, together with a render target.
if (SUCCEEDED(hr))
{
hr = pWICFactory->CreateBitmap(width, height,
GUID_WICPixelFormat32bppBGR,
WICBitmapCacheOnLoad, &pWICBitmap);
}
if (SUCCEEDED(hr))
{
hr = pD2DFactory->CreateWicBitmapRenderTarget(
pWICBitmap, D2D1::RenderTargetProperties(), &pRT);
}
Before rendering text to the render target, some preparatory steps are needed:
if (SUCCEEDED(hr))
{
hr = pDWriteFactory->CreateTextFormat(
fontFamily,
NULL,
DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
fontSize,
L"",
&pTextFormat);
}
if (SUCCEEDED(hr))
{
pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
}
if (SUCCEEDED(hr))
{
hr = pRT->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&pBlackBrush
);
}
Finally, we render text to the bitmap. What’s show below is the simplest case – it’s worth bearing in mind that DirectWrite can do really amazing OpenType wizardry that’s a bit too complex to show here.
if (SUCCEEDED(hr))
{
pRT->BeginDraw();
pRT->Clear(D2D1::ColorF(D2D1::ColorF::White));
D2D1_SIZE_F rtSize = pRT->GetSize();
pRT->DrawText(
markup,
wcslen(markup),
pTextFormat,
D2D1::RectF(0, 0, rtSize.width, rtSize.height),
pBlackBrush);
hr = pRT->EndDraw();
}
Finally, here’s something that’s amazingly easy to do: we just copy the pixels from the bitmap we rendered to to the Bitmap we passed from .Net. Does it ever get more simple?
WICRect r;
r.X = r.Y = 0;
r.Width = width;
r.Height = height;
hr = pWICBitmap->CopyPixels(&r, stride, sizeof(Pixel) * width * height, dst);
Of course, this addition was written for my TypograFix pet project. Meanwhile, let me leave you with the fruits of my labour. The image below was generated using Direct2D & DirectWrite.

Ahh, can life possibly get any better?