Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Rozložení textu DirectWrite lze nakreslit vlastním vykreslovačem textu odvozeným z IDWriteTextRenderer. Vlastní renderer je nutný k využití některých pokročilých funkcí DirectWrite, jako je vykreslování na rastrový obrázek nebo povrch GDI, vložené objekty a klientské kreslicí efekty. Tento kurz popisuje metody IDWriteTextRenderera poskytuje ukázkovou implementaci, která používá Direct2D k vykreslení textu pomocí rastrové výplně.
Tento kurz obsahuje následující části:
- Konstruktor
- DrawGlyphRun()
- DrawUnderline() a DrawStrikethrough()
-
Snapping pixelů, Pixely na DIP a transformace
- IsPixelSnappingDisabled()
- GetCurrentTransform()
- GetPixelsPerDip()
- DrawInlineObject()
- Destruktor
- Použití vlastního vykreslovače textu
Váš vlastní textový renderer musí implementovat metody zděděné z IUnknown kromě metod uvedených na IDWriteTextRenderer referenční stránce a níže.
Úplný zdrojový kód pro renderer vlastního textu naleznete v CustomTextRenderer.cpp a CustomTextRenderer.h soubory DirectWrite Hello World Sample.
Konstruktor
Váš vlastní renderer textu bude potřebovat konstruktor. Tento příklad používá k vykreslení textu plné i rastrové Direct2D štětce.
Z tohoto důvodu konstruktor přebírá parametry nalezené v následující tabulce s popisy.
| Parametr | Popis |
|---|---|
| pD2DFactory | Ukazatel na objekt ID2D1Factory, který se použije k vytvoření potřebných prostředků Direct2D. |
| pRT | Ukazatel na objekt ID2D1HwndRenderTarget, na který bude text vykreslen. |
| pOutlineBrush | Ukazatel na ID2D1SolidColorBrush, který se použije k vykreslení obrysu textu |
| pFillBrush | Ukazatel na ID2D1BitmapBrush, který bude použit k vyplnění textu. |
Tyto budou uloženy konstruktorem, jak je znázorněno v následujícím kódu.
CustomTextRenderer::CustomTextRenderer(
ID2D1Factory* pD2DFactory,
ID2D1HwndRenderTarget* pRT,
ID2D1SolidColorBrush* pOutlineBrush,
ID2D1BitmapBrush* pFillBrush
)
:
cRefCount_(0),
pD2DFactory_(pD2DFactory),
pRT_(pRT),
pOutlineBrush_(pOutlineBrush),
pFillBrush_(pFillBrush)
{
pD2DFactory_->AddRef();
pRT_->AddRef();
pOutlineBrush_->AddRef();
pFillBrush_->AddRef();
}
DrawGlyphRun()
DrawGlyphRun metoda je hlavní metodou zpětného volání rendereru textu. Předává se sada glyfů, které se mají vykreslit spolu s informacemi, jako je počátek základní linie a režim měření. Také předá objekt efektu výkresu klienta, který se použije na spuštění glyphu. Další informace najdete v tématu Jak přidat efekty kreslení klienta do rozložení textu.
Tato implementace vykreslovacího modulu textu vykresluje běhy glyfů jejich převedením na Direct2D geometrie a poté nakreslí a vyplní geometrie. Skládá se z následujících kroků.
Vytvořte objekt ID2D1PathGeometry a potom pomocí metody ID2D1PathGeometry::Open načtěte objekt ID2D1GeometrySink.
// Create the path geometry. ID2D1PathGeometry* pPathGeometry = NULL; hr = pD2DFactory_->CreatePathGeometry( &pPathGeometry ); // Write to the path geometry using the geometry sink. ID2D1GeometrySink* pSink = NULL; if (SUCCEEDED(hr)) { hr = pPathGeometry->Open( &pSink ); }DWRITE_GLYPH_RUN, který se předá DrawGlyphRun, obsahuje objekt IDWriteFontFace s názvem fontFace, který představuje řez písma pro celý běh glyfů. Předejte obrys běhu glyfů do jímky geometrie pomocí metody IDWriteFontFace::GetGlyphRunOutline, jak je ukázáno v následujícím kódu.
// Get the glyph run outline geometries back from DirectWrite and place them within the // geometry sink. if (SUCCEEDED(hr)) { hr = glyphRun->fontFace->GetGlyphRunOutline( glyphRun->fontEmSize, glyphRun->glyphIndices, glyphRun->glyphAdvances, glyphRun->glyphOffsets, glyphRun->glyphCount, glyphRun->isSideways, glyphRun->bidiLevel%2, pSink ); }Po vyplnění geometrické jímky ji zavřete.
// Close the geometry sink if (SUCCEEDED(hr)) { hr = pSink->Close(); }Původ sekvence glyfů musí být upraven tak, aby se vykresloval z výchozí základní linie, jak je znázorněno v následujícím kódu.
// Initialize a matrix to translate the origin of the glyph run. D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F( 1.0f, 0.0f, 0.0f, 1.0f, baselineOriginX, baselineOriginY );baselineOriginX a baselineOriginY se předávají jako parametry metodě zpětného volání DrawGlyphRun.
Vytvořte transformovanou geometrii pomocí metody ID2D1Factory::CreateTransformedGeometry, a to předáním geometrie cesty a matice překladu.
// Create the transformed geometry ID2D1TransformedGeometry* pTransformedGeometry = NULL; if (SUCCEEDED(hr)) { hr = pD2DFactory_->CreateTransformedGeometry( pPathGeometry, &matrix, &pTransformedGeometry ); }Nakonec nakreslete obrys transformované geometrie a vyplňte ji pomocí ID2D1RenderTarget::D rawGeometry a ID2D1RenderTarget::FillGeometry metody a Direct2D štětce uložené jako členské proměnné.
// Draw the outline of the glyph run pRT_->DrawGeometry( pTransformedGeometry, pOutlineBrush_ ); // Fill in the glyph run pRT_->FillGeometry( pTransformedGeometry, pFillBrush_ );Nyní, když jste dokončili kreslení, nezapomeňte vyčistit objekty vytvořené v této metodě.
SafeRelease(&pPathGeometry); SafeRelease(&pSink); SafeRelease(&pTransformedGeometry);
DrawUnderline() a DrawStrikethrough()
IDWriteTextRenderer má také zpětná volání pro kreslení podtržení a přeškrtnutí. Tento příklad nakreslí jednoduchý obdélník pro podtržení nebo přeškrtnutí, ale je možné nakreslit i jiné tvary.
Kreslení podtržení pomocí Direct2D se skládá z následujících kroků.
Nejprve vytvořte D2D1_RECT_F strukturu velikosti a tvaru podtržení. DWRITE_UNDERLINE struktura, která je předána metodě zpětného volání DrawUnderline, poskytuje posun, šířku a tloušťku podtržení.
D2D1_RECT_F rect = D2D1::RectF( 0, underline->offset, underline->width, underline->offset + underline->thickness );Dále vytvořte objekt ID2D1RectangleGeometry pomocí metody ID2D1Factory::CreateRectangleGeometry a inicializované struktury D2D1_RECT_F.
ID2D1RectangleGeometry* pRectangleGeometry = NULL; hr = pD2DFactory_->CreateRectangleGeometry( &rect, &pRectangleGeometry );Stejně jako u spuštění glyfů musí být původ geometrie podtržení přeložen na základě hodnot původu základní linie pomocí metody CreateTransformedGeometry.
// Initialize a matrix to translate the origin of the underline D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F( 1.0f, 0.0f, 0.0f, 1.0f, baselineOriginX, baselineOriginY ); ID2D1TransformedGeometry* pTransformedGeometry = NULL; if (SUCCEEDED(hr)) { hr = pD2DFactory_->CreateTransformedGeometry( pRectangleGeometry, &matrix, &pTransformedGeometry ); }Nakonec nakreslete obrys transformované geometrie a vyplňte ji pomocí metod ID2D1RenderTarget::DrawGeometry a ID2D1RenderTarget::FillGeometry a štětců Direct2D uložených jako členské proměnné.
// Draw the outline of the glyph run pRT_->DrawGeometry( pTransformedGeometry, pOutlineBrush_ ); // Fill in the glyph run pRT_->FillGeometry( pTransformedGeometry, pFillBrush_ );Nyní, když jste dokončili kreslení, nezapomeňte vyčistit objekty vytvořené v této metodě.
SafeRelease(&pRectangleGeometry); SafeRelease(&pTransformedGeometry);
Proces provádění přeškrtnutí je stejný. Přeškrtnutí však bude mít jiný posun a pravděpodobně jinou šířku a tloušťku.
Přichycení pixelů, Pixely na DPI a Transformace
IsPixelSnappingDisabled()
Tato metoda je volána k určení, zda je funkce přichytávání pixelů zakázána. Doporučené výchozí nastavení je FALSEa to je výstup tohoto příkladu.
*isDisabled = FALSE;
GetCurrentTransform()
Tento příklad se vykreslí do cíle vykreslení Direct2D, takže předáte transformaci z cíle vykreslení pomocí ID2D1RenderTarget::GetTransform.
//forward the render target's transform
pRT_->GetTransform(reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform));
GetPixelsPerDip()
Tato metoda se volá k získání počtu pixelů na pixel nezávislý na zařízení (DIP).
float x, yUnused;
pRT_->GetDpi(&x, &yUnused);
*pixelsPerDip = x / 96;
DrawInlineObject()
Vlastní textový renderer má také zpětné volání pro kreslení vložených objektů. V tomto příkladu DrawInlineObject vrátí E_NOTIMPL. Vysvětlení, jak nakreslit vložené objekty, je nad rámec tohoto kurzu. Další informace najdete v tématu Jak přidat vložené objekty do rozložení textu.
Destruktor
Je důležité uvolnit všechny ukazatele, které byly používány vlastní třídou rendereru textu.
CustomTextRenderer::~CustomTextRenderer()
{
SafeRelease(&pD2DFactory_);
SafeRelease(&pRT_);
SafeRelease(&pOutlineBrush_);
SafeRelease(&pFillBrush_);
}
Použití vlastního rendereru textu
Při vykreslování pomocí vlastního rendereru používáte metodu IDWriteTextLayout::Draw, která přebírá jako argument rozhraní zpětného volání odvozené z IDWriteTextRenderer, jak je znázorněno v následujícím kódu.
// Draw the text layout using DirectWrite and the CustomTextRenderer class.
hr = pTextLayout_->Draw(
NULL,
pTextRenderer_, // Custom text renderer.
origin.x,
origin.y
);
Metoda IDWriteTextLayout::Draw volá metody vlastního rendereru, které zadáváte jako zpětné volání. DrawGlyphRun, DrawUnderline, DrawInlineObjecta DrawStrikethrough metody popsané výše provádějí funkce kreslení.