成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

操作實例:閱讀器應用(DirectX 和 XAML)

開發 前端
下面我們介紹如何使用 DirectX、C++ 和 XAML 創建豐富的文檔閱讀器應用。我們涵蓋了此類型應用的結構、技術和最佳實踐,包括如何使用 Virtual Surface Image Source 在 DirectX 繪圖代碼和 XAML 界面管理之間進行交互操作,使用 DirectWrite 加載字體,使用 WIC 加載圖像,以及將 Direct2D 圖像效果應用到圖像。

隨著平板電腦變得越來越普及,融合了閱讀體驗的應用很快就會變得流行起來。 下面我們介紹如何使用 DirectX、C++ 和 XAML 創建豐富的文檔閱讀器應用。我們涵蓋了此類型應用的結構、技術和***實踐,包括如何使用 Virtual Surface Image Source 在 DirectX 繪圖代碼和 XAML 界面管理之間進行交互操作,使用 DirectWrite 加載字體,使用 WIC 加載圖像,以及將 Direct2D 圖像效果應用到圖像。

我們將了解使用 XAML 互操作的 DirectX 雜志應用示例的大量代碼并探討構成應用的不同組件。

雜志示例結構

示例中的文件分為三組:XML、XAML 和 DirectX。XML 組中的文件負責表示 XML 文件(容納有關文章的所有信息)中的每個標記。XAML 組中的文件負責設置 XAML 元素并與Virtual Surface Image Source協作。***,DirectX 組中的文件負責像 DirectWrite 自定義字體加載、Direct2D 圖像效果和 WIC 圖像解碼這樣的事情。

名稱 類型
BindableProperty XAML
ContentImageSource XAML
Design XML
Document XML
Element XML
FontFileStream DirectX
FontLoader DirectX
Image XML
ImageFile XML
ImageFrame XML
Layer XML
List XML
Page XML
PageModel XAML
PageRoll XML
Rectangle XML
Resource XML
Story XML
Text XML
TextFrame XML
TreeIterator XML

 

虛擬圖面圖像源

Virtual Surface Image Source (VSIS)是一個 XAML 管理的呈現圖面,當你要編寫一個涉及平移和縮放的應用時,它將非常有用。此圖面與 DirectX 中的任何其他位圖源相同,除了 XAML 管理 DirectX 和圖像源之間的交互操作這一事實。

當你希望在應用中使用 VSIS 時,你必須:

  • 確定內容的大小。
  • 創建圖像大小的 VSIS
  • 將 DXGI 設備設置為 VSIS 上的設備。
  • 注冊圖像源回調,以便當你需要呈現內容時收到消息。

下面的代碼顯示如何執行這些步驟。

  1. // Measure the content and store its size. 
  2.     Measure(&m_contentSize); 
  3.  
  4.     // Create an image source at the initial pixel size. 
  5.     m_imageSource = ref new VirtualSurfaceImageSource(m_contentSize.cx, m_contentSize.cy); 
  6.  
  7.     ComPtr<IUnknown> unknown(reinterpret_cast<IUnknown*>(m_imageSource)); 
  8.     unknown.As(&m_imageSourceNative); 
  9.  
  10.     auto renderer = m_document->GetRenderer(); 
  11.  
  12.     // Set DXGI device to the image source 
  13.     ComPtr<IDXGIDevice> dxgiDevice; 
  14.     renderer->GetDXGIDevice(&dxgiDevice); 
  15.     m_imageSourceNative->SetDevice(dxgiDevice.Get()); 
  16.  
  17.     // Register image source's update callback so update can be made to it. 
  18.     m_imageSourceNative->RegisterForUpdatesNeeded(this); 

選擇,你有了一個 VSIS 并注冊你的類接收來自虛擬圖面的回調信息。接下來,你必須實現當你需要更新內容時 VSIS 調用的回調方法。

當用戶通過滾動內容來操作 VSIS 時,VSIS 將調用你注冊的類的 UpdatesNeeded 方法。因此,你必須實現 UpdatesNeeded 回調方法。

下面的代碼向你顯示了如何實現 UpdatesNeeded 回調方法和 Draw 幫助程序方法。當 VSISContentImageSource 類上調用此回調方法時,此方法將檢索 VSIS 正在使用 VSISGetUpdateRectCount 方法呈現的更新的矩形。然后,你對此更新的區域調用繪制方法。

  1. / This method is called when the framework needs to update region managed by 
  2. // the virtual surface image source. 
  3. HRESULT STDMETHODCALLTYPE ContentImageSource::UpdatesNeeded() 
  4.     HRESULT hr = S_OK; 
  5.  
  6.     try 
  7.     { 
  8.         ULONG drawingBoundsCount = 0; 
  9.  
  10.         DX::ThrowIfFailed( 
  11.             m_imageSourceNative->GetUpdateRectCount(&drawingBoundsCount) 
  12.             ); 
  13.  
  14.         std::unique_ptr<RECT[]> drawingBounds(new RECT[drawingBoundsCount]); 
  15.  
  16.         DX::ThrowIfFailed( 
  17.             m_imageSourceNative->GetUpdateRects(drawingBounds.get(), drawingBoundsCount) 
  18.             ); 
  19.  
  20.         // This code doesn't try to coalesce multiple drawing bounds into one. Although that 
  21.         // extra process  reduces the number of draw calls, it requires the virtual surface 
  22.         // image source to manage non-uniform tile size, which requires it to make extra copy 
  23.         // operations to the compositor. By using the drawing bounds it directly returns, which are 
  24.         //  non-overlapping  tiles of the same size, the compositor can use these tiles directly, 
  25.         // which can greatly reduce the amount of memory needed by the virtual surface image source. 
  26.         // This results in more draw calls, but Direct2D can accommodate them 
  27.         // without significant impact on presentation frame rate. 
  28.         for (ULONG i = 0; i < drawingBoundsCount; ++i) 
  29.         { 
  30.             if (Draw(drawingBounds[i])) 
  31.             { 
  32.                 // Drawing isn't complete. This can happen when the content is still being 
  33.                 // asynchronously loaded. Inform the image source to invalidate the drawing 
  34.                 // bounds so that it calls back to redraw. 
  35.                 DX::ThrowIfFailed( 
  36.                     m_imageSourceNative->Invalidate(drawingBounds[i]) 
  37.                     ); 
  38.             } 
  39.         } 
  40.     } 
  41.     catch (Platform::Exception^ exception) 
  42.     { 
  43.         hr = exception->HResult; 
  44.     } 
  45.  
  46.     return hr; 
  47.  
  48. bool ContentImageSource::Draw(RECT const& drawingBounds) 
  49.     ComPtr<IDXGISurface> dxgiSurface; 
  50.     POINT surfaceOffset = {0}; 
  51.  
  52.     DX::ThrowIfFailed( 
  53.         m_imageSourceNative->BeginDraw( 
  54.             drawingBounds, 
  55.             &dxgiSurface, 
  56.             &surfaceOffset 
  57.             ) 
  58.         ); 
  59.  
  60.     auto renderer = m_document->GetRenderer(); 
  61.  
  62.     ComPtr<ID2D1DeviceContext> d2dDeviceContext; 
  63.     renderer->GetD2DDeviceContext(&d2dDeviceContext); 
  64.  
  65.     ComPtr<ID2D1Bitmap1> bitmap; 
  66.     DX::ThrowIfFailed( 
  67.         d2dDeviceContext->CreateBitmapFromDxgiSurface( 
  68.             dxgiSurface.Get(), 
  69.             nullptr, 
  70.             &bitmap 
  71.             ) 
  72.         ); 
  73.  
  74.     // Begin the drawing batch 
  75.     d2dDeviceContext->BeginDraw(); 
  76.  
  77.     // Scale content design coordinate to the display coordinate, 
  78.     // then translate the drawing to the designated place on the surface. 
  79.     D2D1::Matrix3x2F transform = 
  80.         D2D1::Matrix3x2F::Scale( 
  81.             m_document->DesignToDisplayWidth(1.0f), 
  82.             m_document->DesignToDisplayHeight(1.0f) 
  83.             ) * 
  84.         D2D1::Matrix3x2F::Translation( 
  85.             static_cast<float>(surfaceOffset.x - drawingBounds.left), 
  86.             static_cast<float>(surfaceOffset.y - drawingBounds.top) 
  87.             ); 
  88.  
  89.     // Prepare to draw content. This is the appropriate time for content element 
  90.     // to draw to an intermediate if there is any. It is important for performance 
  91.     // reason that you don't call SetTarget too often. Preparing the intermediates 
  92.     // upfront reduces the number of times the render target switches back and forth. 
  93.     bool needRedraw = m_content->PrepareToDraw( 
  94.         m_document, 
  95.         transform 
  96.         ); 
  97.  
  98.     if (!needRedraw) 
  99.     { 
  100.         // Set the render target to surface given by the framework 
  101.         d2dDeviceContext->SetTarget(bitmap.Get()); 
  102.  
  103.         d2dDeviceContext->SetTransform(D2D1::IdentityMatrix()); 
  104.  
  105.         // Constrain the drawing to the designated portion of the surface 
  106.         d2dDeviceContext->PushAxisAlignedClip( 
  107.             D2D1::RectF( 
  108.                 static_cast<float>(surfaceOffset.x), 
  109.                 static_cast<float>(surfaceOffset.y), 
  110.                 static_cast<float>(surfaceOffset.x + (drawingBounds.right - drawingBounds.left)), 
  111.                 static_cast<float>(surfaceOffset.y + (drawingBounds.bottom - drawingBounds.top)) 
  112.                 ), 
  113.             D2D1_ANTIALIAS_MODE_ALIASED 
  114.             ); 
  115.  
  116.         // The Clear call must follow the PushAxisAlignedClip call. 
  117.         // Placing the Clear call before the clip is set violates the contract of the 
  118.         // virtual surface image source in that the app draws outside the 
  119.         // designated portion of the surface the image source hands over to it. This 
  120.         // violation won't actually cause the content to spill outside the designated 
  121.         // area because the image source will safeguard it. But this extra protection 
  122.         // has a runtime cost associated with it, and in some drivers this cost can be 
  123.         // very expensive. So the best performance strategy here is to never create a 
  124.         // situation where this protection is required. Not drawing outside the appropriate 
  125.         // clip does that the right way. 
  126.         d2dDeviceContext->Clear(D2D1::ColorF(0, 0)); 
  127.  
  128.         // Draw the content 
  129.         needRedraw = m_content->Draw( 
  130.             m_document, 
  131.             transform 
  132.             ); 
  133.  
  134.         d2dDeviceContext->PopAxisAlignedClip(); 
  135.  
  136.         d2dDeviceContext->SetTarget(nullptr); 
  137.     } 
  138.  
  139.     // End the drawing 
  140.     DX::ThrowIfFailed( 
  141.         d2dDeviceContext->EndDraw() 
  142.         ); 
  143.  
  144.     // Submit the completed drawing to the framework 
  145.     DX::ThrowIfFailed( 
  146.         m_imageSourceNative->EndDraw() 
  147.         ); 
  148.  
  149.     return needRedraw; 

#p#

實現回調后,你的應用現在將從 VSIS 接收有關你需要繪制的區域的信息。你的 draw 函數只需要獲取此矩形,并繪制到 VSIS 的右側區域中。通過實現這兩個回調,并向 VSIS 注冊類,應用便可以在用戶操作內容時呈現到虛擬圖面并更新必要的區域,以顯示更多圖面。

使用 XML 加載內容和綁定數據

我們的應用顯示在雜志中的信息都存儲在 Sample.story 文件中。此文件是一個 XML 文檔,它包含有關文章內容、標題、字體、背景圖像和其他屬性的信息。 應用需要編入摘要的每一部分重要信息都有一個標記。通過使用標記,你可以輕松地展開文章,從該標記的信息中創建對象,以及將該數據綁定到你的應用的 XAML 中。

因為 .story 文件中的信息采用自定義的 XML 架構,所以 TreeIterator.h 中的類幫助分析此 XML 數據并將其置于應用的專用類中。

下面是應用使用的 .story 文件中包含的信息示例。

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <story> 
  3.     <resource> 
  4.         <image name="grasshopper-image" file="grasshopper.jpg"/> 
  5.         <image name="butterfly-image" file="butterfly.jpg"/> 
  6.         <text name="section" font-family="Arial" font-stretch="2" font-size="22">A BUG'S LIFE</text> 
  7.         <text name="grasshopper-title" font-family="Gill Sans" font-stretch="3" font-weight="700" font-size="70">GRASSHOPPER</text> 
  8.         <text name="grasshopper-quote" font-family="Pericles" font-size="18">a slender plant-eating flying and jumping insect that produces a buzzing sound by rubbing its back legs against its forewings</text> 
  9.         <text name="grasshopper-body" font-family="Kootenay" font-size="16"><bold>LOREM</bold> ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. 
  10. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem.</text> 

如 XML 代碼段所示,信息的標記直接對應于應用中的某些 XML 類。當迭代器分析 XML 文件時,將為每個標記創建一個相同名稱的類,在其中存儲標記中的信息。

在我們將 XML 文件中的所有信息都存儲到應用后,你將該數據綁定到 UI 上的元素。此數據綁定存在于兩個位置,頁面的 XAML 標記中及 XAML 標記頁面隨附的 cpp 文件中。在此示例中,它存在于 MainPage.xamlMainPage.cpp 中。

在 XAML 標記中創建 FlipViewDataTemplateScrollViewer 類的實例。然后,將該信息綁定到那些 XAML 標記項。下面是這些元素的 XAML 標記代碼。

  1. <FlipView x:Name="FlipView" ManipulationMode="TranslateInertia"> 
  2.         <FlipView.ItemTemplate> 
  3.             <DataTemplate> 
  4.                 <ScrollViewer ZoomMode="Disabled" VerticalScrollMode="Enabled" IsVerticalRailEnabled="True"> 
  5.                     <ScrollViewer.Background> 
  6.                         <ImageBrush ImageSource="{Binding Background}"/> 
  7.                     </ScrollViewer.Background> 
  8.                     <Image  
  9.                         Source="{Binding Content}"  
  10.                         Width="{Binding ContentWidth}"  
  11.                         Height="{Binding ContentHeight}"  
  12.                         HorizontalAlignment="Left" 
  13.                         /> 
  14.                 </ScrollViewer> 
  15.             </DataTemplate> 
  16.         </FlipView.ItemTemplate> 
  17.     </FlipView> 

此處的代碼顯示,背景和圖像全都具有對應于 XML 源中數據的數據綁定。現在,你需要使用你具有的信息填充這些綁定。你將代碼放置在相同名稱的 cpp 文件中。下面是 MainPage.cpp 中幫助進行數據綁定的代碼。

  1. void MainPage::DocumentLoaded(_In_ Document^ document) 
  2.     // Parse the document into an element tree. 
  3.     document->Parse(); 
  4.  
  5.     auto contentRoot = document->GetContentRoot(); 
  6.  
  7.     if (contentRoot != nullptr) 
  8.     { 
  9.         // Create a collection of content element to bind to the view 
  10.         auto items = ref new Platform::Collections::Vector<Platform::Object^>(); 
  11.  
  12.         auto pageContent = contentRoot->GetFirstChild(); 
  13.  
  14.         while (pageContent != nullptr) 
  15.         { 
  16.             items->Append(ref new PageModel(pageContent, document)); 
  17.  
  18.             pageContent = pageContent->GetNextSibling(); 
  19.         } 
  20.  
  21.         FlipView->ItemsSource = items; 
  22.  
  23.         // Load the saved document state if any 
  24.         LoadState(ApplicationData::Current->LocalSettings->Values); 
  25.  
  26.         m_document = document; 
  27.     } 

此處的代碼分析 XML 文檔,然后創建內容元素的矢量,以便將其綁定到 UI 中的 XAML 元素。

自定義字體加載

要在此 DirectX 應用中使用自定義字體,你必須在 DirectWrite 中實現異步字體加載程序和集合。在 DirectX 應用中,如果你希望提供一個要在文本元素上使用的自定義字體,你需要使用 DirectWrite 獲取未安裝在用戶系統上的新字體。在示例中,可在 FontFileStreamFontLoader 類中找到加載和提供這些新字體的代碼。

FontFileStream 類是 IDWriteFontFileStream 接口的實現,它接受實際字體文件并將其加載到應用可以編入摘要的表單中。這涉及到讀取文件片段、釋放文件片段、獲取文件大小及獲取***編輯時間的處理方法。

下面是用于讀取和釋放字體文件片段的代碼。

  1. HRESULT STDMETHODCALLTYPE FontFileStream::ReadFileFragment( 
  2.     _Outptr_result_bytebuffer_(fragmentSize) void const** fragmentStart, 
  3.     UINT64 fileOffset, 
  4.     UINT64 fragmentSize, 
  5.     _Out_ void** fragmentContext 
  6.     ) 
  7.     // The loader is responsible for doing a bounds check. 
  8.     if (    fileOffset <= m_data->Length 
  9.         &&  fragmentSize + fileOffset <= m_data->Length 
  10.         ) 
  11.     { 
  12.         *fragmentStart = m_data->Data + static_cast<ULONG>(fileOffset); 
  13.         *fragmentContext = nullptr; 
  14.         return S_OK; 
  15.     } 
  16.     else 
  17.     { 
  18.         *fragmentStart = nullptr; 
  19.         *fragmentContext = nullptr; 
  20.         return E_FAIL; 
  21.     } 
  22.  
  23. void STDMETHODCALLTYPE FontFileStream::ReleaseFileFragment( 
  24.     _In_ void* fragmentContext 
  25.     ) 

#p#

下面是用于檢索文件大小和***編輯時間的代碼。

  1. HRESULT STDMETHODCALLTYPE FontFileStream::GetFileSize( 
  2.     _Out_ UINT64* fileSize 
  3.     ) 
  4.     *fileSize = m_data->Length; 
  5.     return S_OK; 
  6.  
  7. HRESULT STDMETHODCALLTYPE FontFileStream::GetLastWriteTime( 
  8.     _Out_ UINT64* lastWriteTime 
  9.     ) 
  10.     // The concept of last write time does not apply to this loader. 
  11.     *lastWriteTime = 0; 
  12.     return E_NOTIMPL; 

在所有片段均已到位并且你可以訪問字體文件中的信息后,你必須編寫允許你從文件流中構造自定義字體集合和字體對象的代碼。可以在 FontLoader.cpp 文件中找到此代碼。

首先,你需要一個函數用于加載和枚舉你要使用的字體。以下代碼用于 LoadAsync 函數,該函數查找雜志示例中的字體目錄,并枚舉該目錄中的 .ttf 字體文件列表。

  1. task<void> FontLoader::LoadAsync() 
  2.     // Locate the "fonts" subfolder within the document folder 
  3.     return task<void>([this]() 
  4.     { 
  5.         task<StorageFolder^>(m_location->GetFolderAsync("fonts")).then([=](StorageFolder^ folder) 
  6.         { 
  7.             // Enumerate a list of .TTF files in the storage location 
  8.             auto filters = ref new Platform::Collections::Vector<Platform::String^>(); 
  9.             filters->Append(".ttf"); 
  10.  
  11.             auto queryOptions = ref new QueryOptions(CommonFileQuery::DefaultQuery, filters); 
  12.             auto queryResult = folder->CreateFileQueryWithOptions(queryOptions); 
  13.  
  14.             return queryResult->GetFilesAsync(); 
  15.  
  16.         }).then([=](IVectorView<StorageFile^>^ files) 
  17.         { 
  18.             m_fontFileCount = files->Size; 
  19.  
  20.             std::vector<task<IBuffer^>> tasks; 
  21.  
  22.             for (uint32 i = 0; i < m_fontFileCount; ++i) 
  23.             { 
  24.                 auto file = dynamic_cast<StorageFile^>(files->GetAt(i)); 
  25.  
  26.                 tasks.push_back(task<IBuffer^>(FileIO::ReadBufferAsync(file))); 
  27.             } 
  28.  
  29.             return when_all(tasks.begin(), tasks.end()); 
  30.  
  31.         }).then([=](std::vector<IBuffer^> buffers) 
  32.         { 
  33.             for each (IBuffer^ buffer in buffers) 
  34.             { 
  35.                 auto fileData = ref new Platform::Array<byte>(buffer->Length); 
  36.                 DataReader::FromBuffer(buffer)->ReadBytes(fileData); 
  37.  
  38.                 ComPtr<FontFileStream> fontFileStream(new FontFileStream(fileData)); 
  39.                 m_fontFileStreams.push_back(fontFileStream); 
  40.             } 
  41.  
  42.         }).wait(); 
  43.     }); 

現在,編寫另一個方法,它采用在 DirectWrite 創建自定義字體集合時傳入的字體集合項。此方法將采用此值并返回字體文件枚舉器。

  1. HRESULT STDMETHODCALLTYPE FontLoader::CreateEnumeratorFromKey( 
  2.     _In_ IDWriteFactory* factory, 
  3.     _In_reads_bytes_(fontCollectionKeySize) void const* fontCollectionKey, 
  4.     uint32 fontCollectionKeySize, 
  5.     _Outptr_ IDWriteFontFileEnumerator** fontFileEnumerator 
  6.     ) 
  7.     *fontFileEnumerator = ComPtr<IDWriteFontFileEnumerator>(this).Detach(); 
  8.     return S_OK; 

此方法接受相同的集合項并返回字體文件流。

  1. HRESULT STDMETHODCALLTYPE FontLoader::CreateStreamFromKey( 
  2.     _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey, 
  3.     uint32 fontFileReferenceKeySize, 
  4.     _Outptr_ IDWriteFontFileStream** fontFileStream 
  5.     ) 
  6.     if (fontFileReferenceKeySize != sizeof(size_t)) 
  7.     { 
  8.         return E_INVALIDARG; 
  9.     } 
  10.  
  11.     size_t fontFileStreamIndex = *(static_cast<size_t const*>(fontFileReferenceKey)); 
  12.  
  13.     *fontFileStream = ComPtr<IDWriteFontFileStream>(m_fontFileStreams.at(fontFileStreamIndex).Get()).Detach(); 
  14.  
  15.     return S_OK; 

接下來的 2 個方法是幫助程序方法。 ***個函數移到文件流中的下一個字體文件,另一個函數用作當前字體文件的簡單 getter。下面是這 2 種方法的代碼。

  1. HRESULT STDMETHODCALLTYPE FontLoader::MoveNext(OUT BOOL* hasCurrentFile) 
  2.     *hasCurrentFile = FALSE; 
  3.  
  4.     if (m_fontFileStreamIndex < m_fontFileCount) 
  5.     { 
  6.         DX::ThrowIfFailed( 
  7.             m_dwriteFactory->CreateCustomFontFileReference( 
  8.                 &m_fontFileStreamIndex, 
  9.                 sizeof(size_t), 
  10.                 this
  11.                 &m_currentFontFile 
  12.                 ) 
  13.             ); 
  14.  
  15.         *hasCurrentFile = TRUE; 
  16.         ++m_fontFileStreamIndex; 
  17.     } 
  18.  
  19.     return S_OK; 
  20.  
  21. HRESULT STDMETHODCALLTYPE FontLoader::GetCurrentFontFile(OUT IDWriteFontFile** currentFontFile) 
  22.     *currentFontFile = ComPtr<IDWriteFontFile>(m_currentFontFile.Get()).Detach(); 
  23.     return S_OK; 

我們的代碼完成后,你現在已擁有一個異步處理應用的正常字體文件加載程序。這 2 個類一起用于枚舉系統上的文件,將它們加載到字體文件流中,并使用你可以使用的這些字體創建一個自定義字體集合。

使用 VSIS 的***實踐

當你希望執行 DirectX 和 XAML 互操作時,Windows 8 支持Surface Image SourceVirtual Surface Image Source,但是具體使用哪一個取決于你希望執行什么操作。

有 3 個主要方案,每一個都有一個 XAML 互操作選項。

  • 繪制元素(如紋理)作為應用中的位圖。
  • 繪制大于屏幕的位圖,因此需要進行平移。
  • 改進觸摸操作的性能。

如果你需要管理靜態圖像或偶然更新 SIS 的內容,則Surface Image Source是一個好的選擇。當 SIS 有用時的一個良好示例是,如果你希望將位圖繪制為 XAML UI 元素。此元素可能需要進行更新以顯示不同的信息,但是大部分是靜態的。SIS 能很好地發揮作用,因為你的應用對 SIS 所做的更新與 XAML UI 線程同步,因此在它需要像應用中的 UI 一樣高性能的方案中運行得***。

但是如果你需要一個需要直接操作(滾動或平移)的較大位圖或 DirectX 內容區域,則使用 VSIS。如果你要顯示的信息不能容納到屏幕或元素上,則 VSIS 會很有用。一個使用 VSIS 的良好示例是具有滾動文本的閱讀應用,或者需要平移和縮放以探索地圖的地圖應用。

如果這些方案中沒有一個匹配你的應用使用情況,則 VSISSIS 可能不適合你的應用。尤其,如果性能對你的應用來說很重要,則 XAML 中的 SwapChainBackgroundPanel 元素可能***。有關詳細信息,請參閱 Windows.UI::Xaml::Controls::SwapChainBackgroundPanel

原文鏈接:http://msdn.microsoft.com/zh-cn/library/windows/apps/jj552955.aspx

責任編輯:陳四芳 來源: microsoft.com
相關推薦

2013-09-02 16:59:34

JavaScriptHTML

2013-09-03 10:40:45

JavaScriptWindows

2013-09-02 16:52:31

Windows 8.1

2011-09-15 18:43:00

UbuntuchmPDF

2014-12-03 10:46:15

iReader

2017-04-11 13:31:40

閱讀器開源RSS

2009-05-05 09:00:48

RSS瀏覽器

2011-09-09 10:19:13

2024-05-16 13:44:18

2020-03-13 19:26:38

Linux電子書閱讀器桌面應用

2014-12-17 15:23:03

Android網絡閱讀器源碼

2023-09-29 11:47:23

2015-12-03 10:04:36

Ncurses工具LNAV

2022-06-02 14:01:54

屏幕閱讀器NVDAWindows

2023-03-23 13:47:00

LinuxEPUB閱讀器

2009-08-27 09:19:51

RSS閱讀器Web 1.0

2016-12-20 09:29:11

AlduinLinuxRSS

2021-05-21 05:26:02

谷歌Chrome 瀏覽器

2010-01-22 14:20:17

Visual C++

2009-07-29 09:35:07

谷歌離職
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91免费在线看 | 91文字幕巨乱亚洲香蕉 | 久久亚洲一区二区三区四区 | 久久精品91久久久久久再现 | 国产成人99久久亚洲综合精品 | 中文字幕在线看 | 欧美日韩中文国产一区发布 | 午夜精品在线观看 | 久久一区二区三区免费 | 中国一级特黄毛片大片 | 伊人一二三 | 欧美日韩在线一区 | 欧美一区二区三区 | 亚洲精品一区二区三区蜜桃久 | 国产超碰人人爽人人做人人爱 | 欧美成人一区二免费视频软件 | 久久国产欧美日韩精品 | 欧美一级片久久 | 美女国产 | 国产精品久久 | 不卡视频一区二区三区 | 国产三级 | www.色.com | 国产精品久久久久久亚洲调教 | 国产精品久久久久久久久久久免费看 | 免费艹逼视频 | 91精品国产一区 | 欧美日韩久| 亚洲九九精品 | 天天拍天天操 | 免费观看一级特黄欧美大片 | 91综合网| 中文字幕1区2区 | 伦理午夜电影免费观看 | 欧美一区二区三区免费电影 | 日本黄色一级片视频 | 亚洲欧美综合精品另类天天更新 | 欧美一区永久视频免费观看 | 怡红院怡春院一级毛片 | 日韩精品一区二区三区在线 | 日韩精品一区二区三区老鸭窝 |