Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Tata letak DirectWriteteks dapat digambar oleh perender teks kustom yang berasal dari IDWriteTextRenderer. Perender kustom diperlukan untuk memanfaatkan beberapa fitur canggih DirectWrite, seperti penyajian ke permukaan bitmap atau GDI, objek sebaris, dan efek gambar klien. Tutorial ini menjelaskan metode IDWriteTextRenderer, dan menyediakan contoh implementasi yang menggunakan Direct2D untuk merender teks dengan isi bitmap.
Tutorial ini berisi bagian-bagian berikut:
- Konstruktor
- DrawglyphRun()
- DrawUnderline() dan DrawStrikethrough()
- Snapping Piksel, Piksel per DIP, dan Transformasi
- DrawInlineObject()
- Destruktor
- Menggunakan Perender Teks Kustom
Perender teks kustom Anda harus menerapkan metode yang diwarisi dari IUnknown selain metode yang tercantum di halaman referensi IDWriteTextRenderer dan di bawah ini.
Untuk kode sumber lengkap untuk perender teks kustom, lihat file CustomTextRenderer.cpp dan CustomTextRenderer.h dari Sampel DirectWrite Halo Dunia.
Konstruktor
Perender teks kustom Anda akan memerlukan konstruktor. Contoh ini menggunakan kuas Direct2D solid dan bitmap untuk merender teks.
Karena itu, konstruktor mengambil parameter yang ditemukan dalam tabel di bawah ini dengan deskripsi.
| Parameter | Deskripsi |
|---|---|
| pD2DFactory | Penunjuk ke objek ID2D1Factory yang akan digunakan untuk membuat sumber daya Direct2D apa pun yang diperlukan. |
| Prt | Penunjuk ke objek ID2D1HwndRenderTarget yang akan dirender teks. |
| pOutlineBrush | Penunjuk ke ID2D1SolidColorBrush yang akan digunakan untuk menggambar kerangka teks |
| pFillBrush | Penunjuk ke ID2D1BitmapBrush yang akan digunakan untuk mengisi teks. |
Ini akan disimpan oleh konstruktor seperti yang ditunjukkan dalam kode berikut.
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()
Metode DrawGlyphRun adalah metode panggilan balik utama dari perender teks. Ini melewati eksekusi glyph yang akan dirender selain informasi seperti asal garis besar dan mode pengukur. Ini juga meneruskan objek efek gambar klien untuk diterapkan ke eksekusi glyph. Untuk informasi selengkapnya, lihat topik Cara Menambahkan Efek Gambar Klien ke Tata Letak Teks .
Implementasi perender teks ini merender eksekusi glyph dengan mengonversinya menjadi geometri Direct2D lalu menggambar dan mengisi geometri. Ini terdiri dari langkah-langkah berikut.
Buat objek ID2D1PathGeometry , lalu ambil objek ID2D1GeometrySink dengan menggunakan metode 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 yang diteruskan ke DrawGlyphRun berisi objek IDWriteFontFace, bernama fontFace, yang mewakili wajah font untuk seluruh eksekusi glyph. Letakkan kerangka eksekusi glyph ke dalam sink geometri dengan menggunakan metode IDWriteFontFace:: GetGlyphRunOutline , seperti yang ditunjukkan dalam kode berikut.
// 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 ); }Setelah mengisi sink geometri, tutup.
// Close the geometry sink if (SUCCEEDED(hr)) { hr = pSink->Close(); }Asal eksekusi glyph harus diterjemahkan sehingga dirender dari asal garis besar yang benar, seperti yang ditunjukkan dalam kode berikut.
// 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 dan baselineOriginY diteruskan sebagai parameter ke metode panggilan balik DrawGlyphRun.
Buat geometri yang diubah dengan menggunakan metode ID2D1Factory::CreateTransformedGeometry dan melewati geometri jalur dan matriks terjemahan.
// Create the transformed geometry ID2D1TransformedGeometry* pTransformedGeometry = NULL; if (SUCCEEDED(hr)) { hr = pD2DFactory_->CreateTransformedGeometry( pPathGeometry, &matrix, &pTransformedGeometry ); }Terakhir, gambar kerangka geometri yang diubah, dan isi dengan menggunakan metode ID2D1RenderTarget::D rawGeometry dan ID2D1RenderTarget::FillGeometry dan kuas Direct2D yang disimpan sebagai variabel anggota.
// Draw the outline of the glyph run pRT_->DrawGeometry( pTransformedGeometry, pOutlineBrush_ ); // Fill in the glyph run pRT_->FillGeometry( pTransformedGeometry, pFillBrush_ );Sekarang setelah Anda selesai menggambar, jangan lupa untuk membersihkan objek yang dibuat dalam metode ini.
SafeRelease(&pPathGeometry); SafeRelease(&pSink); SafeRelease(&pTransformedGeometry);
DrawUnderline() dan DrawStrikethrough()
IDWriteTextRenderer juga memiliki panggilan balik untuk menggambar garis bawah dan coretan. Contoh ini menggambar persegi panjang sederhana untuk garis bawah atau coretan, tetapi bentuk lain dapat digambar.
Menggambar garis bawah dengan menggunakan Direct2D terdiri dari langkah-langkah berikut.
Pertama, buat struktur D2D1_RECT_F ukuran dan bentuk garis bawah. Struktur DWRITE_UNDERLINE yang diteruskan ke metode panggilan balik DrawUnderline memberikan offset, lebar, dan ketebalan garis bawah.
D2D1_RECT_F rect = D2D1::RectF( 0, underline->offset, underline->width, underline->offset + underline->thickness );Selanjutnya, buat objek ID2D1RectangleGeometry dengan menggunakan metode ID2D1Factory::CreateRectangleGeometry dan struktur D2D1_RECT_F yang diinisialisasi.
ID2D1RectangleGeometry* pRectangleGeometry = NULL; hr = pD2DFactory_->CreateRectangleGeometry( &rect, &pRectangleGeometry );Seperti halnya eksekusi glyph, asal geometri garis bawah harus diterjemahkan, berdasarkan nilai asal garis besar, dengan menggunakan metode 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 ); }Terakhir, gambar kerangka geometri yang diubah, dan isi dengan menggunakan metode ID2D1RenderTarget::D rawGeometry dan ID2D1RenderTarget::FillGeometry dan kuas Direct2D yang disimpan sebagai variabel anggota.
// Draw the outline of the glyph run pRT_->DrawGeometry( pTransformedGeometry, pOutlineBrush_ ); // Fill in the glyph run pRT_->FillGeometry( pTransformedGeometry, pFillBrush_ );Sekarang setelah Anda selesai menggambar, jangan lupa untuk membersihkan objek yang dibuat dalam metode ini.
SafeRelease(&pRectangleGeometry); SafeRelease(&pTransformedGeometry);
Proses untuk menggambar coretan adalah sama. Namun, coretan akan memiliki offset yang berbeda, dan kemungkinan lebar dan ketebalan yang berbeda.
Snapping Piksel, Piksel per DIP, dan Transformasi
IsPixelSnappingDisabled()
Metode ini dipanggil untuk menentukan apakah snapping piksel dinonaktifkan. Default yang disarankan adalah FALSE, dan itu adalah output dari contoh ini.
*isDisabled = FALSE;
GetCurrentTransform()
Contoh ini merender ke target render Direct2D, jadi teruskan transformasi dari target render menggunakan ID2D1RenderTarget::GetTransform.
//forward the render target's transform
pRT_->GetTransform(reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform));
GetPixelsPerDip()
Metode ini dipanggil untuk mendapatkan jumlah piksel per Piksel Independen Perangkat (DIP).
float x, yUnused;
pRT_->GetDpi(&x, &yUnused);
*pixelsPerDip = x / 96;
DrawInlineObject()
Perender teks kustom juga memiliki panggilan balik untuk menggambar objek sebaris. Dalam contoh ini, DrawInlineObject mengembalikan E_NOTIMPL. Penjelasan tentang cara menggambar objek sebaris berada di luar lingkup tutorial ini. Untuk informasi selengkapnya, lihat topik Cara Menambahkan Objek Sebaris ke Tata Letak Teks .
Destruktor
Penting untuk melepaskan pointer apa pun yang digunakan oleh kelas perender teks kustom.
CustomTextRenderer::~CustomTextRenderer()
{
SafeRelease(&pD2DFactory_);
SafeRelease(&pRT_);
SafeRelease(&pOutlineBrush_);
SafeRelease(&pFillBrush_);
}
Menggunakan Perender Teks Kustom
Anda merender dengan perender kustom dengan menggunakan metode IDWriteTextLayout::D raw , yang mengambil antarmuka panggilan balik yang berasal dari IDWriteTextRenderer sebagai argumen, seperti yang ditunjukkan dalam kode berikut.
// Draw the text layout using DirectWrite and the CustomTextRenderer class.
hr = pTextLayout_->Draw(
NULL,
pTextRenderer_, // Custom text renderer.
origin.x,
origin.y
);
Metode IDWriteTextLayout::D raw memanggil metode panggilan balik perender kustom yang Anda sediakan. Metode DrawGlyphRun, DrawUnderline, DrawInlineObject, dan DrawStrikethrough yang dijelaskan di atas melakukan fungsi gambar.