Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
DirectWriteukład tekstu można narysować za pomocą niestandardowego renderera tekstu pochodzącego z IDWriteTextRenderer. Niestandardowy moduł renderujący jest wymagany do korzystania z niektórych zaawansowanych funkcji DirectWrite, takich jak renderowanie na powierzchniach bitmapy lub GDI, obiekty osadzone i efekty rysowania po stronie klienta. W tym samouczku opisano metody IDWriteTextRendereri przedstawiono przykładową implementację, która używa Direct2D do renderowania tekstu z wypełnieniem mapy bitowej.
Ten samouczek zawiera następujące części:
- Konstruktor
- DrawGlyphRun()
- DrawUnderline() i DrawStrikethrough()
- Przyciąganie pikseli, Piksele na DIP i Przekształcanie
- DrawInlineObject()
- Destruktor
- Przy użyciu niestandardowego modułu renderowania tekstu
Niestandardowy moduł renderowania tekstu musi implementować metody dziedziczone z interfejsu IUnknown, a także metody wymienione na stronie referencyjnej IDWriteTextRenderer oraz poniżej.
Pełny kod źródłowy niestandardowego modułu renderowania tekstu można znaleźć w plikach CustomTextRenderer.cpp i CustomTextRenderer.h DirectWrite Hello World Sample.
Konstruktor
Niestandardowy moduł renderowania tekstu będzie potrzebował konstruktora. W tym przykładzie do renderowania tekstu użyto zarówno jednolitych, jak i bitmapowych Direct2D pędzli.
W związku z tym konstruktor przyjmuje parametry znalezione w poniższej tabeli z opisami.
| Parametr | Opis |
|---|---|
| pD2DFactory | Wskaźnik do obiektu ID2D1Factory, który będzie używany do tworzenia wszystkich potrzebnych zasobów Direct2D. |
| pRT | Wskaźnik do obiektu ID2D1HwndRenderTarget, do którego zostanie renderowany tekst. |
| pOutlineBrush | Wskaźnik do ID2D1SolidColorBrush, który będzie używany do rysowania konturu tekstu |
| pFillBrush | Wskaźnik do ID2D1BitmapBrush, który będzie użyty do wypełnienia tekstu. |
Będą one przechowywane przez konstruktora, jak pokazano w poniższym kodzie.
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()
Metoda DrawGlyphRun jest główną metodą wywołania zwrotnego renderowania tekstu. Jest przekazywany przebieg glifów, które mają być renderowane oprócz informacji, takich jak źródło punktu odniesienia i tryb pomiaru. Przekazuje również obiekt efektu rysowania klienta, który ma zostać zastosowany do ciągu glifów. Aby uzyskać więcej informacji, zobacz temat Jak dodać efekty rysowania klienta do układu tekstu.
Ta implementacja modułu renderowania tekstu renderuje przebiegi glifów, konwertując je na geometrie Direct2D, a następnie rysując i wypełniając geometrie. Obejmuje to następujące kroki.
Utwórz obiektID2D1PathGeometry, a następnie pobierz obiekt ID2D1GeometrySink przy użyciu metody ID2D1PathGeometry::Open.
// 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 przekazywany do DrawGlyphRun zawiera obiekt IDWriteFontFace o nazwie fontFace, który reprezentuje krój pisma dla całego przebiegu glifów. Umieść kontur glifu w odbiorniku geometrii przy użyciu metody IDWriteFontFace:: GetGlyphRunOutline, jak pokazano w poniższym kodzie.
// 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 wypełnieniu bufora geometrii, zamknij go.
// Close the geometry sink if (SUCCEEDED(hr)) { hr = pSink->Close(); }Źródło przebiegu glif musi zostać przetłumaczone, aby było renderowane z prawidłowego źródła punktu odniesienia, jak pokazano w poniższym kodzie.
// 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 i baselineOriginY są przekazywane jako parametry metody DrawGlyphRun wywołania zwrotnego.
Utwórz przekształconą geometrię, używając metody ID2D1Factory::CreateTransformedGeometry i przekazując geometrię ścieżki oraz macierz translacji.
// Create the transformed geometry ID2D1TransformedGeometry* pTransformedGeometry = NULL; if (SUCCEEDED(hr)) { hr = pD2DFactory_->CreateTransformedGeometry( pPathGeometry, &matrix, &pTransformedGeometry ); }Na koniec narysuj kontur przekształconej geometrii i wypełnij ją przy użyciu metod ID2D1RenderTarget::DrawGeometry i ID2D1RenderTarget::FillGeometry oraz pędzli Direct2D przechowywanych jako zmienne składowe.
// Draw the outline of the glyph run pRT_->DrawGeometry( pTransformedGeometry, pOutlineBrush_ ); // Fill in the glyph run pRT_->FillGeometry( pTransformedGeometry, pFillBrush_ );Po zakończeniu rysowania nie zapomnij wyczyścić obiektów utworzonych w tej metodzie.
SafeRelease(&pPathGeometry); SafeRelease(&pSink); SafeRelease(&pTransformedGeometry);
DrawUnderline() i DrawStrikethrough()
IDWriteTextRenderer ma również wywołania zwrotne dla rysowania podkreśleń i przekreśleń. W tym przykładzie rysowany jest prosty prostokąt dla podkreślenia lub przekreślenia, ale można narysować inne kształty.
Rysowanie podkreślenia przy użyciu Direct2D składa się z poniższych kroków.
Najpierw utwórz strukturę D2D1_RECT_F o rozmiarze i kształcie podkreślenia. Struktura DWRITE_UNDERLINE, przekazywana do metody zwrotnej DrawUnderline, określa przesunięcie, szerokość i grubość podkreślenia.
D2D1_RECT_F rect = D2D1::RectF( 0, underline->offset, underline->width, underline->offset + underline->thickness );Następnie, używając metody ID2D1Factory::CreateRectangleGeometry, utwórz obiekt ID2D1RectangleGeometry, korzystając z zainicjowanej struktury D2D1_RECT_F.
ID2D1RectangleGeometry* pRectangleGeometry = NULL; hr = pD2DFactory_->CreateRectangleGeometry( &rect, &pRectangleGeometry );Podobnie jak w przypadku uruchomienia glifów, pochodzenie geometrii podkreślenia musi zostać przetłumaczone na podstawie wartości punktu odniesienia pochodzenia przy użyciu 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 ); }Na koniec narysuj kontur przekształconej geometrii i wypełnij ją przy użyciu metod ID2D1RenderTarget::DrawGeometry i ID2D1RenderTarget::FillGeometry oraz pędzli Direct2D przechowywanych jako zmienne składowe.
// Draw the outline of the glyph run pRT_->DrawGeometry( pTransformedGeometry, pOutlineBrush_ ); // Fill in the glyph run pRT_->FillGeometry( pTransformedGeometry, pFillBrush_ );Po zakończeniu rysowania nie zapomnij wyczyścić obiektów utworzonych w tej metodzie.
SafeRelease(&pRectangleGeometry); SafeRelease(&pTransformedGeometry);
Proces rysowania linii przekreślenia jest taki sam. Jednak przekreślenie będzie miało inne przesunięcie i prawdopodobnie inną szerokość i grubość.
Przyciąganie pikseli, piksele na DIP i przekształcanie
IsPixelSnappingDisabled()
Ta metoda jest wywoływana w celu określenia, czy przyciąganie pikseli jest wyłączone. Zalecaną wartością domyślną jest falsei jest to dane wyjściowe tego przykładu.
*isDisabled = FALSE;
GetCurrentTransform()
W tym przykładzie renderowany jest obiekt docelowy renderowania Direct2D, więc przekaż przekształcenie z obiektu docelowego renderowania przy użyciu ID2D1RenderTarget::GetTransform.
//forward the render target's transform
pRT_->GetTransform(reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform));
GetPixelsPerDip()
Ta metoda jest wywoływana w celu uzyskania liczby pikseli na piksel niezależny od urządzenia (DIP).
float x, yUnused;
pRT_->GetDpi(&x, &yUnused);
*pixelsPerDip = x / 96;
DrawInlineObject()
Niestandardowy silnik renderowania tekstu ma również wywołanie zwrotne do rysowania obiektów wewnątrz liniowych. W tym przykładzie funkcja DrawInlineObject zwraca E_NOTIMPL. Wyjaśnienie sposobu rysowania obiektów wbudowanych wykracza poza zakres tego samouczka. Aby uzyskać więcej informacji, zobacz temat "Jak dodawać obiekty wbudowane do układu tekstu".
Destruktor
Ważne jest, aby zwolnić wszystkie wskaźniki, których używała niestandardowa klasa renderowania tekstu.
CustomTextRenderer::~CustomTextRenderer()
{
SafeRelease(&pD2DFactory_);
SafeRelease(&pRT_);
SafeRelease(&pOutlineBrush_);
SafeRelease(&pFillBrush_);
}
Korzystanie z niestandardowego modułu renderowania tekstu
Renderowanie za pomocą niestandardowego modułu renderowania odbywa się przy użyciu metody IDWriteTextLayout::Draw, która przyjmuje interfejs do wywoływania zwrotnego pochodzący z IDWriteTextRenderer jako argument, jak pokazano w poniższym kodzie.
// 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 wywołuje metody przekazanego przez Ciebie niestandardowego wywołania zwrotnego renderera. Metody DrawGlyphRun, DrawUnderline, DrawInlineObjecti DrawStrikethrough metody rysowania opisane powyżej wykonują funkcje rysunku.