Bagikan melalui


Penyajian Teks dengan Direct2D dan DirectWrite

Tidak seperti API lain, seperti GDI, GDI+ atau WPF, Direct2D beroperasi dengan API lain, DirectWrite, untuk memanipulasi dan merender teks. Topik ini menjelaskan manfaat dan interoperaksi komponen terpisah ini.

Topik ini berisi bagian berikut.

Direct2D Memungkinkan Adopsi Inkremental

Memindahkan aplikasi dari satu API grafis ke API grafis lainnya bisa sulit atau tidak apa yang Anda inginkan karena berbagai alasan. Ini mungkin karena Anda harus mendukung plug-in yang masih mengambil antarmuka yang lebih lama, karena aplikasi itu sendiri terlalu besar untuk di-port ke API baru dalam satu rilis atau karena beberapa bagian dari API yang lebih baru diinginkan tetapi API yang lebih lama berfungsi cukup baik untuk bagian lain dari aplikasi.

Karena Direct2D dan DirectWrite diimplementasikan sebagai komponen terpisah, Anda dapat meningkatkan seluruh sistem grafis 2D atau hanya bagian teksnya. Misalnya, Anda dapat memperbarui aplikasi untuk menggunakan DirectWrite untuk teks tetapi masih menggunakan GDI atau GDI+ untuk penyajian.

Layanan Teks versus Penyajian Teks

Seiring berkembangnya aplikasi, persyaratan pemrosesan teks mereka telah berkembang semakin kompleks. Pada awalnya, teks umumnya terbatas pada UI yang ditata secara statis, dan teks dirender dalam kotak yang ditentukan dengan baik, seperti tombol. Ketika aplikasi mulai tersedia dalam jumlah bahasa yang terus bertambah, pendekatan ini menjadi lebih sulit untuk dipertahankan karena lebar dan tinggi teks yang diterjemahkan dapat bervariasi secara signifikan antar bahasa. Untuk beradaptasi, aplikasi mulai secara dinamis menjabarkan UI mereka untuk bergantung pada ukuran teks yang dirender aktual, alih-alih sebaliknya.

Untuk membantu aplikasi menyelesaikan tugas ini, DirectWrite menyediakan antarmuka IDWriteTextLayout. API ini memungkinkan aplikasi untuk menentukan sepotong teks dengan karakteristik kompleks seperti font dan ukuran font yang berbeda, garis bawah, coretan, teks dua arah, efek, elipsis, dan bahkan karakter non-glyph yang disematkan (seperti emotikon bitmap atau ikon). Aplikasi kemudian dapat mengubah berbagai karakteristik teks karena secara berulang menentukan tata letak UI-nya. Sampel DirectWrite Halo Dunia, yang ditunjukkan dalam ilustrasi berikut dan dalam Tutorial: Memulai topik DirectWrite, menunjukkan banyak efek ini.

cuplikan layar sampel

Tata letak dapat memposisikan glyph secara ideal berdasarkan lebarnya (seperti yang dilakukan WPF), atau dapat memposisikan glyph ke posisi piksel terdekat (seperti yang dilakukan GDI ).

Selain mendapatkan pengukuran teks, aplikasi dapat menekan uji berbagai bagian teks. Misalnya, mungkin ingin mengetahui bahwa hyperlink dalam teks diklik. (Untuk informasi selengkapnya tentang pengujian hit, lihat topik Cara Melakukan Pengujian Hit pada Tata Letak Teks .)

Antarmuka tata letak teks diputar dari API penyajian yang digunakan aplikasi, seperti yang ditunjukkan oleh diagram berikut:

tata letak teks dan diagram api grafis.

Pemisahan ini dimungkinkan karena DirectWrite menyediakan antarmuka penyajian (IDWriteTextRenderer) yang dapat diterapkan aplikasi untuk merender teks dengan menggunakan API grafis apa pun yang Anda inginkan. Aplikasi yang menerapkan metode panggilan balik IDWriteTextRenderer::D rawGlyphRun dipanggil oleh DirectWrite saat merender tata letak teks. Merupakan tanggung jawab metode ini untuk melakukan operasi menggambar atau meneruskannya.

Untuk menggambar glyph, Direct2D menyediakan ID2D1RenderTarget::D rawGlyphRun untuk menggambar ke permukaan Direct2D dan DirectWrite menyediakan IDWriteBitmapRenderTarget::D rawGlyphRun untuk menggambar ke permukaan GDI yang kemudian dapat ditransfer ke jendela dengan menggunakan GDI. Dengan mudah, DrawGlyphRun di Direct2D dan DirectWrite memiliki parameter yang sama persis dengan metode DrawGlyphRun yang diterapkan aplikasi pada IDWriteTextRenderer.

Mengikuti pemisahan serupa, fitur khusus teks (seperti enumerasi dan manajemen font, analisis glyph, dan sebagainya) ditangani oleh DirectWrite alih-alih Direct2D. Objek DirectWrite diterima langsung oleh Direct2D. Untuk membantu aplikasi GDI yang ada untuk memanfaatkan DirectWrite, aplikasi ini menyediakan antarmuka metode IDWriteGdiInterop dengan metode untuk melakukan hal berikut:

Glyph versus Teks

Teks adalah sekumpulan titik kode Unicode (karakter), dengan berbagai pengubah gaya (font, bobot, garis bawah, coretan, dan sebagainya) yang ditata dalam persegi panjang. Glyph, sebaliknya, adalah indeks tertentu ke dalam file font tertentu. Glyph mendefinisikan sekumpulan kurva yang dapat dirender, tetapi, tidak memiliki arti tekstual. Berpotensi ada pemetaan banyak ke banyak antara glyph dan karakter. Urutan glyph yang berasal dari Wajah Font yang sama dan yang ditata secara berurutan pada garis besar disebut GlyphRun. Baik DirectWrite dan Direct2D memanggil API rendering glyph mereka yang paling tepat DrawGlyphRun dan mereka memiliki tanda tangan yang sangat mirip. Berikut ini dari ID2D1RenderTarget di Direct2D:

STDMETHOD_(void, DrawGlyphRun)(
        D2D1_POINT_2F baselineOrigin,
        __in CONST DWRITE_GLYPH_RUN *glyphRun,
        __in ID2D1Brush *foregroundBrush,
        DWRITE_MEASURING_MODE measuringMode = DWRITE_MEASURING_MODE_NATURAL 
        ) PURE;

Dan metode ini berasal dari IDWriteBitmapRenderTarget di DirectWrite:

STDMETHOD(DrawGlyphRun)(
        FLOAT baselineOriginX,
        FLOAT baselineOriginY,
        DWRITE_MEASURING_MODE measuringMode,
        __in DWRITE_GLYPH_RUN const* glyphRun,
        IDWriteRenderingParams* renderingParams,
        COLORREF textColor,
        __out_opt RECT* blackBoxRect = NULL
        ) PURE;

Versi DirectWrite menyimpan asal garis besar, mode ukur, dan parameter eksekusi glyph dan menyertakan parameter tambahan.

DirectWrite juga memungkinkan Anda menggunakan perender kustom untuk glyph dengan mengimplementasikan antarmuka IDWriteTextRenderer. Antarmuka ini juga memiliki metode DrawGlyphRun , seperti yang ditunjukkan oleh contoh kode berikut.

STDMETHOD(DrawGlyphRun)(
        __maybenull void* clientDrawingContext,
        FLOAT baselineOriginX,
        FLOAT baselineOriginY,
        DWRITE_MEASURING_MODE measuringMode,
        __in DWRITE_GLYPH_RUN const* glyphRun,
        __in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
        __maybenull IUnknown* clientDrawingEffect
        ) PURE;

Versi ini mencakup lebih banyak parameter yang berguna saat Anda menerapkan perender teks kustom. Parameter akhir digunakan untuk efek gambar kustom yang diimplementasikan aplikasi. (Untuk informasi selengkapnya tentang efek gambar klien lihat Cara Menambahkan Efek Gambar Klien ke Tata Letak Teks.

Setiap eksekusi glyph dimulai dari asal dan diletakkan pada garis mulai dari asal ini. Glyph diubah oleh transformasi dunia saat ini dan pengaturan penyajian teks yang dipilih pada target render terkait. API ini umumnya dipanggil langsung hanya oleh aplikasi yang melakukan tata letak mereka sendiri (Misalnya prosesor Word) atau oleh aplikasi yang telah menerapkan antarmuka IDWriteTextRenderer.

DirectWrite dan Direct2D

Direct2D menyediakan layanan penyajian tingkat glyph melalui DrawGlyphRun. Namun, ini mengharuskan aplikasi untuk mengimplementasikan detail penyajian, yang pada dasarnya mereproduksi fungsionalitas DrawText API dari GDI sendiri.

Oleh karena itu, Direct2D menyediakan API yang menerima teks alih-alih glyph: ID2D1RenderTarget::D rawTextLayout dan ID2D1RenderTarget::D rawText. Kedua metode dirender ke permukaan Direct2D. Untuk merender ke permukaan GDI, IDWriteBitmapRenderTarget::D rawGlyphRun disediakan. Tetapi metode ini memerlukan perender teks kustom untuk diimplementasikan oleh aplikasi. (Untuk informasi selengkapnya, lihat topik Render to a GDI Surface .)

Penggunaan teks aplikasi biasanya dimulai sederhana: letakkan OK atau Batal pada tombol tata letak tetap, misalnya. Namun, seiring waktu, itu menjadi lebih kompleks karena internasionalisasi dan fitur lain ditambahkan. Akhirnya banyak aplikasi harus menggunakan objek tata letak teks DirectWrite dan mengimplementasikan perender teks.

Oleh karena itu, Direct2D menyediakan API berlapis yang memungkinkan aplikasi untuk memulai secara sederhana dan tumbuh lebih canggih tanpa harus melacak kembali atau meninggalkan kode kerja mereka. Tampilan yang disederhanakan diperlihatkan dalam diagram berikut:

diagram aplikasi directwrite dan direct2d.

DrawText

DrawText adalah API paling sederhana untuk digunakan. Dibutuhkan string Unicode, kuas latar depan, objek format tunggal, dan persegi panjang tujuan. Ini akan menjabarkan dan merender seluruh string dalam persegi tata letak, dan secara opsional mengklipnya. Ini berguna ketika Anda meletakkan sepotong teks sederhana dalam sepotong antarmuka pengguna tata letak tetap.

DrawTextLayout

Dengan membuat objek IDWriteTextLayout , aplikasi dapat mulai mengukur dan mengatur teks dan elemen UI lainnya, dan mendukung beberapa font, gaya, garis bawah, dan coretan. Direct2D menyediakan DRAWTextLayout API yang langsung menerima objek ini dan merender teks pada titik tertentu. (Lebar dan tinggi disediakan oleh objek tata letak). Selain mengimplementasikan semua fitur tata letak teks yang diharapkan, Direct2D akan menginterpretasikan objek efek apa pun sebagai kuas dan menerapkan kuas tersebut ke rentang glyph yang dipilih. Ini juga akan memanggil objek sebaris apa pun. Aplikasi kemudian dapat menyisipkan karakter non-glyph (ikon) ke dalam teks jika diinginkan. Keuntungan lain menggunakan objek tata letak teks adalah posisi glyph di-cache di dalamnya. Oleh karena itu, perolehan performa yang besar dimungkinkan dengan menggunakan kembali objek tata letak yang sama untuk beberapa panggilan gambar dan menghindari menghitung ulang posisi glyph untuk setiap panggilan. Kemampuan ini tidak ada untuk DrawText GDI.

DrawGlyphRun

Akhirnya, aplikasi dapat mengimplementasikan antarmuka IDWriteTextRenderer itu sendiri dan memanggil DrawGlyphRun dan FillRectangle itu sendiri, atau API penyajian lainnya. Semua interaksi yang ada dengan objek Tata Letak Teks akan tetap tidak berubah.

Untuk contoh cara mengimplementasikan perender teks kustom, lihat topik Render Menggunakan Perender Teks Kustom .

Penyajian Glyph

Menambahkan DirectWrite ke aplikasi GDI yang ada memungkinkan aplikasi menggunakan API IDWriteBitmapRenderTarget untuk merender glyph. Metode IDWriteBitmapRenderTarget::D rawGlyphRun yang DirectWrite sediakan akan merender dalam warna solid ke DC memori tanpa memerlukan API tambahan apa pun, seperti Direct2D.

Ini memungkinkan aplikasi untuk mendapatkan fitur penyajian teks tingkat lanjut seperti berikut:

  • ClearType sub-piksel memungkinkan aplikasi untuk meletakkan glyph pada posisi sub-piksel untuk memungkinkan penyajian glyph tajam dan tata letak glyph.
  • Antialias arah Y memungkinkan penyajian kurva yang lebih halus pada glyph yang lebih besar.

Aplikasi yang pindah ke Direct2D juga akan mendapatkan fitur-fitur berikut:

  • Akselerasi perangkat keras.
  • Kemampuan untuk mengisi teks dengan sikat Direct2D arbitrer, seperti gradien radial, gradien linier, dan bitmap.
  • Dukungan lainnya untuk lapisan dan kliping melalui API PushAxisAlignedClip, PushLayer , dan CreateCompatibleRenderTarget .
  • Kemampuan untuk mendukung penyajian teks Skala Abu-abu. Ini mengisi saluran alfa tujuan dengan benar sesuai dengan opasitas kuas teks dan antialias teks.

Untuk mendukung akselerasi perangkat keras secara efisien, Direct2D menggunakan perkiraan yang sedikit berbeda untuk koreksi Gamma yang disebut koreksi alfa. Ini tidak memerlukan Direct2D untuk memeriksa piksel warna target render saat merender teks.

Kesimpulan

Topik ini menjelaskan perbedaan dan kesamaan antara Direct2D dan DirectWrite dan motivasi arsitektur untuk menyediakannya sebagai API koperasi yang terpisah.