What*s New in Direct2D and DirectWrite for Windows 10

Direct2D
Reader
Project Spartan
Windows 8.1
Windows 8.1
void Setup()
{
m_dwriteFactory->CreateCustomRenderingParams(
gamma,
enhancedContrast,
grayscaleEnhancedContrast,
clearTypeLevel,
pixelGeometry,
DWRITE_RENDERING_MODE_OUTLINE,
gridFitMode,
&m_outlineParams
);
}
void OnRender(
{
if (animating)
{
d2dContext->SetTextRenderingParams(
m_outlineParams.Get()
);
}
d2dContext->DrawTextLayout(/* … */);
}
When do I use
vector text?
Windows 8.1
spDwriteFactory->GetSystemFontCollection(
TRUE, // include downloadable fonts
&spFontCollection
);
spDwriteFactory->CreateTextFormat(
L"Gabriola",
spFontCollection,
/* ... */
&spTextFormat
);
class MyFontDownloadListener : IDWriteFontDownloadListener
{
STDMETHOD_(void, DownloadCompleted)( /* ... */)
{
RerenderDocument();
}
}
spDwriteFactory->GetFontDownloadQueue(/* ... */, &spQueue);
spQueue->AddListener(/* ... */);
spQueue->BeginDownload();
When do I use
downloadable
fonts?
Windows 8.1
IDWriteFontCollection
IDWriteFontSet
Family name
Family name; Postscript
name; Script/language;
Weight;
…
Requires implementing
loader callback interface
Simple builder pattern
Local and downloadable
Local and downloadable
Local only
Local and downloadable
spDwriteFactory->GetSystemFontSet(
&spSystemFontSet
);
DWRITE_FONT_PROPERTY properties =
{
{ DWRITE_FONT_PROPERTY_ID_STYLE, L"2" /* italic */, nullptr },
{ DWRITE_FONT_PROPERTY_ID_WEIGHT, L"700" /* bold */, nullptr },
};
ComPtr<IDWriteFontSet> spMatchingFonts
spSystemFontSet->GetMatchingFonts(
properties,
ARRAYSIZE(properties),
&spMatchingFonts
);
Windows 8.1
bool JpegYCbCrOptimizationsRenderer::DoesWicSupportRequestedYCbCr()
{
ComPtr<IWICPlanarBitmapSourceTransform> wicPlanarSource;
HRESULT hr = m_wicScaler.As(&wicPlanarSource);
if (SUCCEEDED(hr))
{
BOOL isTransformSupported;
uint32 supportedWidth = m_cachedBitmapPixelWidth;
uint32 supportedHeight = m_cachedBitmapPixelHeight;
DX::ThrowIfFailed(
wicPlanarSource->DoesSupportTransform(
&supportedWidth,
&supportedHeight,
WICBitmapTransformRotate0,
WICPlanarOptionsDefault,
SampleConstants::WicYCbCrFormats,
m_planeDescriptions,
SampleConstants::NumPlanes,
&isTransformSupported
)
);
auto wicFactory = m_deviceResources->GetWicImagingFactory();
auto d2dContext = m_deviceResources->GetD2DDeviceContext();
ComPtr<IWICPlanarBitmapSourceTransform> wicPlanarSource;
DX::ThrowIfFailed(
m_wicScaler.As(&wicPlanarSource)
);
ComPtr<IWICBitmap> bitmaps[SampleConstants::NumPlanes];
ComPtr<IWICBitmapLock> locks[SampleConstants::NumPlanes];
WICBitmapPlane planes[SampleConstants::NumPlanes];
for (uint32 i = 0; i < SampleConstants::NumPlanes; i++)
{
DX::ThrowIfFailed(
wicFactory->CreateBitmap(
m_planeDescriptions[i].Width,
m_planeDescriptions[i].Height,
m_planeDescriptions[i].Format,
WICBitmapCacheOnLoad,
&bitmaps[i]
)
);
if ((isTransformSupported == TRUE) &&
(supportedWidth == m_cachedBitmapPixelWidth) &&
(supportedHeight == m_cachedBitmapPixelHeight))
{
return true;
}
LockBitmap(bitmaps[i].Get(), WICBitmapLockWrite, nullptr, &locks[i], &planes[i]);
}
DX::ThrowIfFailed(
wicPlanarSource->CopyPixels(
nullptr,
m_cachedBitmapPixelWidth,
m_cachedBitmapPixelHeight,
WICBitmapTransformRotate0,
WICPlanarOptionsDefault,
planes,
SampleConstants::NumPlanes
)
);
}
return false;
}
bool JpegYCbCrOptimizationsRenderer::DoesDriverSupportYCbCr()
{
auto d2dContext = m_deviceResources->GetD2DDeviceContext();
if ((d2dContext->IsDxgiFormatSupported(DXGI_FORMAT_R8_UNORM)) &&
(d2dContext->IsDxgiFormatSupported(DXGI_FORMAT_R8G8_UNORM)))
{
return true;
}
DX::ThrowIfFailed(d2dContext->CreateEffect(CLSID_D2D1YCbCr, &m_d2dYCbCrEffect));
ComPtr<ID2D1Bitmap1> d2dBitmaps[SampleConstants::NumPlanes];
for (uint32 i = 0; i < SampleConstants::NumPlanes; i++)
{
locks[i] = nullptr;
DX::ThrowIfFailed(d2dContext->CreateBitmapFromWicBitmap(bitmaps[i].Get(), &d2dBitmaps[i]));
m_d2dYCbCrEffect->SetInput(i, d2dBitmaps[i].Get());
}
return false;
}
void JpegYCbCrOptimizationsRenderer::CreateYCbCrDeviceResources()
{
}
void JpegYCbCrOptimizationsRenderer::CreateDeviceIndependentResources()
{
auto wicFactory = m_deviceResources->GetWicImagingFactory();
ComPtr<IWICBitmapDecoder> decoder;
DX::ThrowIfFailed(
wicFactory->CreateDecoderFromFilename(
L"mammoth.jpg",
nullptr,
GENERIC_READ,
WICDecodeMetadataCacheOnDemand,
&decoder
)
);
ComPtr<IWICBitmapFrameDecode> frameDecode;
DX::ThrowIfFailed(
decoder->GetFrame(0, &frameDecode)
);
uint32 imageWidth, imageHeight;
DX::ThrowIfFailed(
frameDecode->GetSize(&imageWidth, &imageHeight)
);
void JpegYCbCrOptimizationsRenderer::LockBitmap(
_In_ IWICBitmap *pBitmap,
DWORD bitmapLockFlags,
_In_opt_ const WICRect *prcSource,
_Outptr_ IWICBitmapLock **ppBitmapLock,
_Out_ WICBitmapPlane *pPlane
)
{
ComPtr<IWICBitmapLock> lock;
DX::ThrowIfFailed(pBitmap->Lock(prcSource, bitmapLockFlags, &lock));
DX::ThrowIfFailed(lock->GetStride(&pPlane->cbStride));
DX::ThrowIfFailed(lock->GetDataPointer(&pPlane->cbBufferSize, &pPlane->pbBuffer));
DX::ThrowIfFailed(lock->GetPixelFormat(&pPlane->Format));
*ppBitmapLock = lock.Detach();
}
void JpegYCbCrOptimizationsRenderer::CreateBgraDeviceResources()
{
auto wicFactory = m_deviceResources->GetWicImagingFactory();
auto d2dContext = m_deviceResources->GetD2DDeviceContext();
GetDisplayResolution();
float horzScale = static_cast<float>(m_displayResolutionX) / static_cast<float>(imageWidth);
float vertScale = static_cast<float>(m_displayResolutionY) / static_cast<float>(imageHeight);
float scale = min(horzScale, min(vertScale, 1.0f));
m_cachedBitmapPixelWidth = static_cast<uint32>(imageWidth * scale);
m_cachedBitmapPixelHeight = static_cast<uint32>(imageHeight * scale);
ComPtr<IWICFormatConverter> formatConverter;
DX::ThrowIfFailed(wicFactory->CreateFormatConverter(&formatConverter));
DX::ThrowIfFailed(
formatConverter->Initialize(
m_wicScaler.Get(),
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
nullptr,
0.0L,
WICBitmapPaletteTypeCustom
)
);
DX::ThrowIfFailed(
wicFactory->CreateBitmapScaler(&m_wicScaler)
);
DX::ThrowIfFailed(
m_wicScaler->Initialize(
frameDecode.Get(),
m_cachedBitmapPixelWidth,
m_cachedBitmapPixelHeight,
WICBitmapInterpolationModeLinear
)
);
ComPtr<ID2D1Bitmap1> bgraBitmap;
DX::ThrowIfFailed(d2dContext->CreateBitmapFromWicBitmap(formatConverter.Get(), &bgraBitmap));
DX::ThrowIfFailed(d2dContext->CreateEffect(CLSID_D2D12DAffineTransform, &m_d2dTransformEffect));
m_d2dTransformEffect->SetInput(0, bgraBitmap.Get());
}
}
void JpegYCbCrOptimizationsRenderer::CreateDeviceDependentResources(bool forceBgra)
{
if (forceBgra == false)
{
if (DoesWicSupportRequestedYCbCr() && DoesDriverSupportYCbCr())
{
CreateYCbCrDeviceResources();
m_sampleMode = YCbCrSupportMode::Enabled;
}
else
{
CreateBgraDeviceResources();
m_sampleMode = YCbCrSupportMode::DisabledFallback;
}
}
else
{
CreateBgraDeviceResources();
m_sampleMode = YCbCrSupportMode::DisabledForced;
}
}
offset.height = (size.Height - DX::ConvertPixelsToDips(static_cast<float>(m_cachedBitmapPixelHeight),
dpi) * scale) / 2;
D2D1::Matrix3x2F transform =
D2D1::Matrix3x2F::Scale(scale, scale) *
D2D1::Matrix3x2F::Translation(offset);
switch (m_sampleMode)
{
case YCbCrSupportMode::DisabledFallback:
case YCbCrSupportMode::DisabledForced:
DX::ThrowIfFailed(
m_d2dTransformEffect->SetValue(
D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX,
transform
)
);
break;
case YCbCrSupportMode::Enabled:
DX::ThrowIfFailed(
m_d2dYCbCrEffect->SetValue(
D2D1_YCBCR_PROP_TRANSFORM_MATRIX,
transform
)
);
void JpegYCbCrOptimizationsRenderer::CreateWindowSizeDependentResources()
{
if (m_deviceResourceTaskMode == Completed)
{
auto size = m_deviceResources->GetLogicalSize();
float dpi = m_deviceResources->GetDpi();
float horzScale = size.Width /
DX::ConvertPixelsToDips(static_cast<float>(m_cachedBitmapPixelWidth), dpi);
float vertScale = size.Height /
DX::ConvertPixelsToDips(static_cast<float>(m_cachedBitmapPixelHeight), dpi);
float scale = min(horzScale, min(vertScale, 1.0f));
D2D1_SIZE_F offset;
offset.width = (size.Width DX::ConvertPixelsToDips(static_cast<float>(m_cachedBitmapPixelWidth), dpi) * scale) / 2;
break;
case YCbCrSupportMode::Unknown:
default:
DX::ThrowIfFailed(E_FAIL);
}
}
}
void Setup()
{
m_spD2DFactory->CreateImageSourceFromWic(
spWicBitmapSource,
loadingOptions,
alphaMode,
&m_spImageSource);
}
void OnRender()
{
m_spDrawingContext->DrawImage(m_spImageSource);
}
Gaussian blur
Contrast
effect
Saturation
effect
Exposure
effect
Sharpen
effect
Temp/tint
effect
Shader pass 1
Shader pass 2
Shader pass 3
Contrast
effect
Exposure
effect
Temp/tint
effect
Saturation
effect
Sharpen
effect
Shader pass 4
Shader pass 5
Shader pass 1
Contrast
effect
Saturation
effect
Exposure
effect
Sharpen
effect
Shader pass 2
Temp/tint
effect
here
Analysis
Histogram
Filter
Gaussian blur
Directional blur
Convolve matrix
Morphology
Edge Detection
Composite
Composite
Arithmetic composite
Blend
Transparency
Luminance to alpha
Chroma key
Photo
Brightness
Contrast
Exposure
Grayscale
Highlights and Shadows
Invert
Sepia
Sharpen
Straighten
Temperature and Tint
Vignette
Source
Bitmap source
Flood
Turbulence
Stylize
Point-specular
Spot-specular
Distant-specular
Point-diffuse
Spot-diffuse
Distant-diffuse
Shadow
Displacement map
Emboss
Posterize
Transform
Tile
Crop
Border
Scale
2D affine transform
3D perspective transform
3D transform
Atlas
DPI Compensation
Color
Discrete transfer
Table transfer
Linear transfer
Gamma transfer
Color matrix
Saturation
Hue rotation
Color management
Premultiply
Unpremultiply
DPI compensation
Opacity metadata
YCbCr
HueToRgb
RgbToHue
Lookup Table 3D
here
Windows 8.1
D2D1_GRADIENT_MESH patchList[] =
{
D2D1::GradientMeshPatch(
D2D1::Point2F(10, 110),
/* ... */
D2D1::Point2F(110, 10),
D2D1::ColorF(D2D1::ColorF::Green),
/* ... */
D2D1::ColorF(D2D1::ColorF::Orange),
D2D1_PATCH_EDGE_MODE_ANTIALIASED,
D2D1_PATCH_EDGE_MODE_ANTIALIASED,
D2D1_PATCH_EDGE_MODE_ANTIALIASED,
D2D1_PATCH_EDGE_MODE_ALIASED)
};
// (bottom left corner)
// (upper right corner)
// (bottom left corner)
// (upper right corner)
void Setup()
{
spD2dContext->CreateGradientMesh(
patchList,
ARRAYSIZE(patchList),
&m_spGradientMesh
));
}
void OnRender()
{
spD2dContext->DrawGradientMesh(m_spGradientMesh);
}
MSDN
MSDN
MSDN
#
Title
Speakers
Time
631
Introducing Win2D: DirectX-powered Drawing in C#
Simon Tao
Wed 2:00 – 3:00
681
Introducing Direct Ink: Learn how to Unlock New Opportunities Using
Ink in Your App
Sriram Subramanian; Ryan Harris (Silicon
Benders); Miles Harris (Silicon Benders)
Thurs 2:00 – 3:00
705
Harness the full power of Digital Inking in your Universal Windows app
with Ink Recognition, Advanced Ink Processing and more
Francis Zhou; Xiao Tu
Thurs 5:00 – 6:00