Upload
brooke-foster
View
253
Download
8
Embed Size (px)
Citation preview
Anthony HodsdonSoftware Developer, Windows GraphicsWhat’s New in Direct2D and DirectWrite for Windows 10
What’s New in Direct2D and DirectWrite for Windows 10
3-775
What are Direct2D and DirectWrite?Text and Font Handling EnhancementsImaging EnhancementsEffect EnhancementsNew 2D Primitives
Agenda
Direct2D and DirectWrite
What are Direct2D and DirectWrite?
DirectWrite
Fonts Layout
Direct2D
Text
What are Direct2D and DirectWrite?
XAMLDWM
Shell
Reader Project Spartan
Win2D
Text
Scalable text rendering improvements
Standard text rendering:• Bitmap-based glyph cache• Optimized for fixed zoom levels but• Requires re-rasterization at each
text size • Inappropriate for text zooming
Scalable text rendering improvements
Windows 8.1
Common mitigation:• Render to a bitmap and scale• Fast but produces blurry results
Scalable text rendering improvements
Windows 8.1
Accelerated vector text rendering:• Improved vector text rendering
algorithm• Hardware glyph cache extended to
support size-independent vector text
• Net result: both fast and crisp text while zooming
Scalable text rendering improvements
Windows 10
Vector text demo
void Setup(){ m_dwriteFactory->CreateCustomRenderingParams( gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, DWRITE_RENDERING_MODE_OUTLINE, gridFitMode, &m_outlineParams );}
Scalable text rendering improvements
void OnRender({ if (animating) { d2dContext->SetTextRenderingParams( m_outlineParams.Get() ); }
d2dContext->DrawTextLayout(/* … */);}
Scalable text rendering improvements
Suggested usage:• Use standard text rendering for
static text to get the best possible quality
• Switch to vector text rendering during manipulations and animations
• Best on feature level 10+ hardware
Scalable text rendering improvements
When do I use vector text?
Font selection
Fonts
• Developers can target phone, tablet, and PC but
• Not all fonts available on phone• Full suite of desktop fonts: ~½ GB
• Net result: Inconsistent document viewing experience
Font selection
Windows 8.1
Windows 10 divides fonts into two classes:• Recommended fonts:
• Guaranteed available on all devices• Includes common UI and document fonts
• Optional fonts:• May or may not be present on all devices• Hosted in the cloud via a Microsoft service• Downloadable just-in-time during app
execution
Downloadable fonts
Windows 10
Key features:• Asynchronous
• Pending fonts use font fallback
• Global font cache• Downloadable fonts can be shared across
processes• Size of cache scales depending on the
device
• Supported in both DirectX and XAML apps
Downloadable fonts
Windows 10
Downloadable fonts demo
spDwriteFactory->GetSystemFontCollection( TRUE, // include downloadable fonts &spFontCollection );
spDwriteFactory->CreateTextFormat( L"Gabriola", spFontCollection, /* ... */ &spTextFormat );
Downloadable fonts
class MyFontDownloadListener : IDWriteFontDownloadListener{ STDMETHOD_(void, DownloadCompleted)( /* ... */) { RerenderDocument(); }}
spDwriteFactory->GetFontDownloadQueue(/* ... */, &spQueue);spQueue->AddListener(/* ... */);spQueue->BeginDownload();
Downloadable fonts
Suggested usage:• Use fonts in the recommended set
for UI text• Ensures UI is consistent, even when offline• Limits bandwidth usage when online
• Use downloadable fonts to maintain document fidelity
Downloadable fonts
When do I use downloadable fonts?
Font enumeration
Fonts
Font collections:• Highly structured mechanism for
enumerating fonts
Font enumeration
Windows 8.1
Font sets:• More flexible alternative to font
collections
Font enumeration
Windows 10
Font enumeration
Font collections and font sets compared
IDWriteFontCollection IDWriteFontSet
Filtering criteria Family name
Family name; Postscript name; Script/language; Weight;…
Custom construction
Requires implementing loader callback interface
Simple builder pattern
Font selection Local and downloadable Local and downloadable
Font property queries Local only Local and downloadable
Plus: Easy interop between font collections and font sets
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 );
Font enumeration
Image loading and rendering
Different APIs for different scenarios:• CreateBitmapFromWicBitmap• Bitmap source effect• YCbCr effect
Substantial amount of code required to get optimal performance
Image loading and rendering
Windows 8.1
YCbCr image loading in Windows 8.1 (Part 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 ) ); if ((isTransformSupported == TRUE) && (supportedWidth == m_cachedBitmapPixelWidth) && (supportedHeight == m_cachedBitmapPixelHeight)) { return true; } } 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; } return false;}
void JpegYCbCrOptimizationsRenderer::CreateYCbCrDeviceResources(){
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] ) ); LockBitmap(bitmaps[i].Get(), WICBitmapLockWrite, nullptr, &locks[i], &planes[i]); } DX::ThrowIfFailed( wicPlanarSource->CopyPixels( nullptr, m_cachedBitmapPixelWidth, m_cachedBitmapPixelHeight, WICBitmapTransformRotate0, WICPlanarOptionsDefault, planes, SampleConstants::NumPlanes ) ); 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()); }}
YCbCr image loading in Windows 8.1 (Part 2)
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(); ComPtr<IWICFormatConverter> formatConverter; DX::ThrowIfFailed(wicFactory->CreateFormatConverter(&formatConverter)); DX::ThrowIfFailed( formatConverter->Initialize( m_wicScaler.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.0L, WICBitmapPaletteTypeCustom ) ); 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::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) ); 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); DX::ThrowIfFailed( wicFactory->CreateBitmapScaler(&m_wicScaler) ); DX::ThrowIfFailed( m_wicScaler->Initialize( frameDecode.Get(), m_cachedBitmapPixelWidth, m_cachedBitmapPixelHeight, WICBitmapInterpolationModeLinear ) );}
YCbCr image loading in Windows 8.1 (Part 3)
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 ) ); break; case YCbCrSupportMode::Unknown: default: DX::ThrowIfFailed(E_FAIL); } }}
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; }} 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;
Image source:• Simple, efficient API for loading and
rendering images
Image loading and rendering
Windows 10
void Setup(){ m_spD2DFactory->CreateImageSourceFromWic( spWicBitmapSource, loadingOptions, alphaMode, &m_spImageSource);}
void OnRender(){ m_spDrawingContext->DrawImage(m_spImageSource);}
Image loading and rendering
Image source advantages:• Support for arbitrarily large images• Easy integration with printing and
effects• Numerous baked-in optimizations
Image loading and rendering
Windows 10
Image effect optimizations
Image effect optimizations
What are image effects?
Saturation
Hue rotation
Gaussian blur
Image effect optimizations
Contrast effect
Exposure effect
Temp/tint effect
Saturation effect
Image effect optimizations
Contrast effect
Exposure effect
Temp/tint effect
Saturation effect
Shader pass 1 Shader pass 2 Shader pass 3
Shader pass 4 Shader pass 5
Windows 8.1:
Image effect optimizations
Contrast effect
Exposure effect
Temp/tint effect
Saturation effect
Shader pass 1
Shader pass 2
Windows 10 (Shader linking):
Shader linking demo
• Built-in effects get shader linking applied automatically.
• Custom effects should use new HLSL macros. (See details here)
Image effect optimizations
How can I use shader linking in my app?
New image effects
New image effectsAnalysisHistogram
FilterGaussian blurDirectional blurConvolve matrixMorphologyEdge Detection
CompositeCompositeArithmetic compositeBlend
TransparencyLuminance to alphaChroma key
PhotoBrightnessContrastExposureGrayscaleHighlights and ShadowsInvertSepiaSharpenStraightenTemperature and TintVignette
SourceBitmap sourceFloodTurbulence
StylizePoint-specularSpot-specularDistant-specularPoint-diffuseSpot-diffuseDistant-diffuseShadowDisplacement mapEmbossPosterize
TransformTileCropBorderScale2D affine transform3D perspective transform3D transformAtlasDPI Compensation
ColorDiscrete transferTable transferLinear transferGamma transferColor matrixSaturationHue rotationColor managementPremultiplyUnpremultiplyDPI compensationOpacity metadataYCbCrHueToRgbRgbToHueLookup Table 3D
New 2D primitives
Inking
Inking
Windows 10
Composition
XAML Ink Canvas
Direct2D
Input
Ink Presenter
…Graphics
New Features:• Hardware accelerated• Low latency• High fidelity
Inking
Windows 10
Inking demo
Check out DirectInk talks here for more details.
Inking
Learn more
Gradients
Gradients
Windows 8.1
Two types of gradients:
Linear gradientbrush
Radial gradientbrush
Gradients
Windows 10
New, more flexible gradient type:
Gradient Mesh
Gradients
Gradient mesh patch:• 4 colors• 16 positional control
points
D2D1_GRADIENT_MESH patchList[] ={ D2D1::GradientMeshPatch( D2D1::Point2F(10, 110), // (bottom left corner) /* ... */ D2D1::Point2F(110, 10), // (upper right corner) D2D1::ColorF(D2D1::ColorF::Green), // (bottom left corner) /* ... */ D2D1::ColorF(D2D1::ColorF::Orange), // (upper right corner) D2D1_PATCH_EDGE_MODE_ANTIALIASED, D2D1_PATCH_EDGE_MODE_ANTIALIASED, D2D1_PATCH_EDGE_MODE_ANTIALIASED, D2D1_PATCH_EDGE_MODE_ALIASED)};
Gradients
void Setup(){ spD2dContext->CreateGradientMesh( patchList, ARRAYSIZE(patchList), &m_spGradientMesh ));}
void OnRender(){ spD2dContext->DrawGradientMesh(m_spGradientMesh);}
Gradients
Gradient mesh demo
In Windows 10, your DirectX application will be:
• Faster
• More maintainable
• More consistent across devices
• More beautiful
Summary
Direct2D Documentation: MSDNDirectWrite Documentation: MSDNFont Usage Documentation: MSDN
Resources and related sessions
# Title Speakers Time631 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
© 2015 Microsoft Corporation. All rights reserved.