Vykreslování textu pomocí Direct2D a DirectWrite
Na rozdíl od jiných rozhraní API, jako jsou GDI, GDI+ nebo WPF, Direct2D spolupracuje s API DirectWritek manipulaci a vykreslování textu. Toto téma popisuje výhody a spolupráci těchto samostatných komponent.
Toto téma obsahuje následující části.
- Direct2D umožňuje přírůstkovou adopci
- Textové služby versus vykreslování textu
- Symboly versus text
-
DirectWrite a Direct2D
- KresliText
- NakreslitTextovýLayout
- DrawGlyphRun
- vykreslování glyfů
- závěr
Direct2D umožňuje přírůstkové přijetí
Přesunutí aplikace z jednoho grafického rozhraní API do jiného může být obtížné nebo není to, co chcete z různých důvodů. Důvodem může být to, že musíte podporovat moduly plug-in, které stále přebírají starší rozhraní, protože samotná aplikace je příliš velká na portování do nového rozhraní API v jedné verzi, nebo proto, že některá část novějšího rozhraní API je žádoucí, ale starší rozhraní API funguje dostatečně dobře pro ostatní části aplikace.
Vzhledem k tomu, že Direct2D a DirectWrite jsou implementované jako samostatné komponenty, můžete upgradovat celý 2D grafický systém nebo jenom textovou část. Aplikaci můžete například aktualizovat tak, aby používala directWrite pro text, ale stále k vykreslování používejte GDI nebo GDI+.
Textové služby a vykreslování textu
S vývojem aplikací se požadavky na zpracování textu stále složitější. Zpočátku byl text obecně omezen na staticky rozložené uživatelské rozhraní a text se vykresloval v dobře definovaném poli, jako je například tlačítko. Vzhledem k tomu, že aplikace začaly být dostupné v rostoucím počtu jazyků, byl tento přístup obtížnější udržet, protože šířka i výška přeloženého textu se mezi jazyky může výrazně lišit. Aplikace se začaly dynamicky přizpůsobovat uživatelským rozhraním tak, aby závisely na skutečné vykreslené velikosti textu, místo aby tomu bylo naopak.
Pro usnadnění dokončení této úlohy DirectWrite poskytuje rozhraní IDWriteTextLayout. Toto rozhraní API umožňuje aplikaci určit část textu se složitými vlastnostmi, jako jsou různá písma a velikosti písma, podtržení, přeškrtnutí, obousměrný text, efekty, tři tečky a dokonce vložené neglyfové znaky (například rastrový emotikona nebo ikona). Aplikace pak může změnit různé vlastnosti textu, protože iterativním způsobem určuje rozložení uživatelského rozhraní. Ukázka DirectWrite Hello World, která je znázorněna na následujícím obrázku a v tématu tutoriálu: Začínáme s DirectWrite, ukazuje mnoho z těchto efektů.
Rozložení může ideálně umístit glyfy na základě jejich šířky (stejně jako WPF), nebo může přichytit glyfy k nejbližším pixelovým pozicím (jak to dělá GDI).
Kromě získání měření textu může aplikace provádět test úderů na různé části textu. Může například chtít vědět, že je v textu kliknut na hypertextový odkaz. (Další informace o testování zásahů naleznete v tématu Jak provést testování zásahů v rozložení textu.)
Rozhraní rozložení textu je oddělené od vykreslovacího rozhraní API, které aplikace používá, jak ukazuje následující diagram:
Toto oddělení je možné, protože DirectWrite poskytuje rozhraní pro vykreslování (IDWriteTextRenderer), které aplikace mohou implementovat k vykreslení textu pomocí libovolného grafického rozhraní API. Aplikace implementovaná IDWriteTextRenderer::DrawGlyphRun zpětnou volací metodu volá DirectWrite při vykreslování textového rozložení. Je úlohou této metody provádět kreslicí operace nebo je předat dál.
Pro kreslení glyfů poskytuje Direct2DID2D1RenderTarget::DrawGlyphRun pro kreslení na plochu Direct2D a DirectWrite poskytuje IDWriteBitmapRenderTarget::DrawGlyphRun pro kreslení na plochu GDI, která se pak dá přenést do okna pomocí GDI. Výhodně, DrawGlyphRun v Direct2D i DirectWrite mají přesně kompatibilní parametry s metodou DrawGlyphRun, kterou aplikace používá v IDWriteTextRenderer.
Po podobném oddělení se funkce specifické pro text (například výčty a správa písem, analýza glyfů atd.) zpracovávají DirectWrite místo Direct2D. DirectWrite objekty jsou přijímány přímo Direct2D. DirectWrite poskytuje rozhraní metod IDWriteGdiInterop, které pomáhá stávajícím aplikacím GDI využít výhody tím, že nabízí následující metody:
- Vytvořte písmo DirectWrite z logického písma GDI pomocíCreateFontFromLOGFONT.
- Převeďte z řezu písma DirectWrite na logické písmo GDI (ConvertFontFaceToLOGFONT).
- Načtěte DirectWrite písmo z vybraného do HDC. (CreateFontFaceFromHdc)
- Vytvořte cíl vykreslení rastrového obrázku v systémové paměti (CreateBitmapRenderTarget).
Glyfy vs text
Text je sada bodů kódu Unicode (znaků) s různými stylistickými modifikátory (písma, váhy, podtržení, přeškrtnutí atd.), které jsou rozložené v obdélníku. Naproti tomu glyf je konkrétní index do konkrétního souboru písma. Glyf definuje sadu křivek, které lze vykreslit, ale nemá žádný textový význam. Existuje možné mapování M:N mezi glyfy a znaky. Posloupnost glyfů, které pocházejí ze stejného řezu písma a které jsou rozloženy postupně na účaří, se nazývá GlyphRun. DirectWrite i Direct2D volají nejpřesnější vykreslovací rozhraní API DrawGlyphRun a mají velmi podobné podpisy. Následující text je z ID2D1RenderTarget v 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;
A tato metoda pochází z IDWriteBitmapRenderTarget v 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;
Verze DirectWrite uchovává základní původ, režim měření a parametry spuštění glyphu a obsahuje další parametry.
DirectWrite také umožňuje použít vlastní Renderer pro glyfy implementací rozhraní IDWriteTextRenderer. Toto rozhraní má také metodu DrawGlyphRun, jak ukazuje následující příklad kódu.
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;
Tato verze obsahuje další parametry, které jsou užitečné při implementaci vlastního textového rendereru. Poslední parametr se používá pro vlastní efekty kreslení implementované aplikací. (Další informace o efektech výkresu klienta naleznete v tématu Jak přidat efekty výkresu klienta do rozložení textu.
Každá sekvence glyfů začíná na počátku a je umístěna na řádek začínající od tohoto počátku. Glyfy se mění podle aktuálního světového transformu a vybraného nastavení vykreslování textu na přidruženém cílovém objektu vykreslování. Toto API se obvykle volá přímo pouze aplikacemi, které provádějí vlastní rozložení (například textový editor), nebo aplikacemi, které implementovaly rozhraní IDWriteTextRenderer.
DirectWrite a Direct2D
Direct2D poskytuje služby vykreslování na úrovni glyph prostřednictvím DrawGlyphRun. To však vyžaduje, aby aplikace implementovala podrobnosti vykreslování, které v podstatě samy reprodukují funkčnost rozhraní DrawText API z GDI.
Proto Direct2D poskytuje rozhraní API, která přijímají text místo glyfů: ID2D1RenderTarget::DrawTextLayout a ID2D1RenderTarget::DrawText. Obě metody vykreslují na plochu Direct2D. K vykreslování na povrch GDI je k dispozici IDWriteBitmapRenderTarget::DrawGlyphRun. Tato metoda ale vyžaduje, aby aplikace implementovala vlastní renderer textu. (Další informace najdete v tématu Vykreslení na povrch GDI.)
Použití textu v aplikaci obvykle začíná jednoduše: umístěte OK nebo Zrušit na tlačítko s pevným rozmístěním, například. V průběhu času se ale stává složitější, protože se přidávají internacionalizace a další funkce. V konečném důsledku bude mnoho aplikací muset používat objekty rozložení textu DirectWrite a implementovat vykreslování textu.
Proto Direct2D poskytuje vrstvená rozhraní API, která umožňují aplikaci jednoduše začít a rozvíjet sofistikovanější aplikace, aniž by bylo nutné vracet se zpět nebo opustit existující kód. Zjednodušené zobrazení je znázorněno v následujícím diagramu:
DrawText
DrawText je z rozhraní API nejsnazší na použití. Vezme řetězec Unicode, štětec popředí, formátovací objekt a cílový obdélník. Rozloží a vykreslí celý řetězec v rámci rozvrhového obdélníku a volitelně ho vystřihne. To je užitečné, když vložíte jednoduchý text do části uživatelského rozhraní s pevným rozložením.
KreslitRozvrženíTextu
Vytvořením objektu IDWriteTextLayout může aplikace začít měřit a uspořádávat text a další prvky uživatelského rozhraní a podporovat více písem, stylů, podtržení a přeškrtnutí. direct2D poskytuje rozhraní API DrawTextLayout, které přímo přijímá tento objekt a vykresluje text v daném okamžiku. (Šířka a výška jsou poskytovány objektem rozložení). Kromě implementace všech očekávaných funkcí rozložení textu bude Direct2D interpretovat jakýkoli objekt efektu jako štětec a použije tento štětec na vybraný rozsah glyfů. Bude také volat všechny vložené objekty. Aplikace pak může do textu vložit jiné než glyfové znaky (ikony), pokud si přeje. Další výhodou použití objektu rozložení textu je, že pozice glyfů jsou uloženy do mezipaměti. Proto je možné dosáhnout velkého zvýšení výkonu opětovným použitím stejného objektu rozložení pro více volání kreslení a vyhnout se přepočítání pozic glyf pro každé volání. Tato funkce není k dispozici pro GDI DrawText.
DrawGlyphRun
Aplikace může implementovat rozhraní IDWriteTextRenderer a volat DrawGlyphRun a FillRectangle sama nebo jakékoli jiné API pro vykreslování. Veškerá existující interakce s objektem Rozložení textu zůstane beze změny.
Příklad implementace vlastního vykreslovače textu najdete v tématu Vykreslení pomocí vlastního vykreslovacího modulu textu.
Vykreslování glyfů
Přidání DirectWrite do existující aplikace GDI umožňuje aplikaci používat IDWriteBitmapRenderTarget API k vykreslení glyfů. IDWriteBitmapRenderTarget::DrawGlyphRun metoda, kterou DirectWrite poskytuje, vykreslí v plné barvě do paměťového DC bez nutnosti dalších API, jako je Direct2D.
To aplikaci umožňuje získat pokročilé funkce vykreslování textu, například následující:
- ClearType v dílčích pixelech umožňuje aplikaci umístit glyfy na pozice pod pixely, aby umožňovala ostré vykreslování glyfů i rozložení glyfů.
- Antialiasing ve směru Y umožňuje plynulejší vykreslování křivek na větších glyfech.
Aplikace, která přejde na Direct2D, získá také následující funkce:
- Hardwarová akcelerace.
- Možnost vyplnit text libovolným štětcem Direct2D , jako jsou radiální přechody, lineární přechody a rastrové obrázky.
- Další podpora vrstvení a výřezu prostřednictvím API PushAxisAlignedClip, PushLayer a CreateCompatibleRenderTarget.
- Schopnost podporovat vykreslování textu v odstínech šedé. Tím se správně naplní cílový alfa kanál v závislosti na krycí vrstvě textu a antialiasingu textu.
Pro efektivní podporu hardwarové akcelerace Direct2D používá mírně odlišnou aproximaci gamma korekce, která se nazývá alfa korekce. To nevyžaduje, aby direct2D při vykreslování textu kontroloval cílový barevný pixel vykreslení.
Závěr
Toto téma vysvětluje rozdíly a podobnosti mezi Direct2D a DirectWrite a motivací architektury pro jejich poskytování jako samostatná spolupracující rozhraní API.