Vlastní sady písem
Toto téma popisuje různé způsoby použití vlastních písem v aplikaci.
- Úvod
- souhrn rozhraní API
- klíčové koncepty
- Formáty písem a písem
- sady písem a kolekce písem
- běžné scénáře
- pokročilé scénáře
Úvod
Aplikace ve většině případů používají písma nainstalovaná místně v systému. DirectWrite poskytuje přístup k těmto písmům pomocí IDWriteFactory3::GetSystemFontSet nebo IDWriteFactory::GetSystemFontCollection metod. V některých případech můžou aplikace také chtít používat písma, která jsou součástí Windows 10, ale aktuálně nejsou nainstalovaná v aktuálním systému. K těmto písmům lze přistupovat ze služby písem Windows pomocí metody GetSystemFontSet nebo voláním IDWriteFactory3::GetSystemFontCollection s includeDownloadableFonts nastaveným na HODNOTU TRUE.
V některých scénářích aplikací ale aplikace musí používat písma, která nejsou nainstalovaná v systému a nejsou poskytována službou Windows Font Service. Tady jsou příklady takových scénářů:
- Písma se vkládají jako prostředky v binárním souboru aplikace.
- Soubory písem jsou součástí balíčku aplikace a ukládají se na disk pod instalační složkou aplikace.
- Aplikace je nástroj pro vývoj písem, který potřebuje načíst soubory písem určené uživatelem.
- Písma jsou vložená do souborů dokumentů, které je možné zobrazit nebo upravit v aplikaci.
- Aplikace používá písma získaná z veřejné webové služby písem.
- Aplikace používá data písem streamovaná přes privátní síťový protokol.
DirectWrite poskytuje rozhraní API pro práci s vlastními písmy v těchto a dalších podobných scénářích. Vlastní data písma můžou pocházet ze souborů v místním systému souborů; ze vzdálených cloudových zdrojů, ke které se přistupuje pomocí protokolu HTTP; nebo z libovolných zdrojů po načtení do vyrovnávací paměti.
Poznámka
I když DirectWrite poskytuje rozhraní API pro práci s vlastními písmy od Windows 7, novější rozhraní API byla přidána ve Windows 10 a znovu ve Windows 10 Creators Update (preview build 15021 nebo novější), která usnadňují implementaci několika zmíněných scénářů. Toto téma se zaměřuje na rozhraní API dostupná v okně 10. Informace o aplikacích, které potřebují pracovat se staršími verzemi Windows, najdete v tématu vlastních kolekcí písem (Windows 7/8).
Souhrn rozhraní API
Toto téma se zaměřuje na funkce poskytované následujícími rozhraními API:
- rozhraní IDWriteFontSet
- rozhraní IDWriteFontSetBuilder
- rozhraní IDWriteFontSetBuilder1
- rozhraní IDWriteFontFaceReference
- rozhraní IDWriteFontFile
- metoda IDWriteFactory::CreateFontFileReference
- metoda IDWriteFactory::CreateCustomFontFileReference
- metod IDWriteFactory3::CreateFontFaceReference
- struktura DWRITE_FONT_PROPERTY
- výčet DWRITE_FONT_PROPERTY_ID
- rozhraní IDWriteFontFileLoader
- metoda IDWriteFactory::RegisterFontFileLoader
- metoda IDWriteFactory::UnregisterFontFileLoader
- metoda IDWriteFactory5::CreateInMemoryFontFileLoader
- rozhraní IDWriteInMemoryFontFileLoader
- metoda IDWriteFactory5::CreateHttpFontFileLoader
- rozhraní IDWriteRemoteFontFileLoader
- rozhraní IDWriteFontDownloadQueue
- rozhraní IDWriteFontDownloadListener
- rozhraní IDWriteFontFileStream
- rozhraní IDWriteRemoteFontFileStream
- rozhraní IDWriteAsyncResult
- metoda IDWriteFactory5::AnalyzeContainerType
- metoda IDWriteFactory5::UnpackFontFile
Klíčové koncepty
Abyste porozuměli rozhraním API DirectWrite pro práci s vlastními písmy, může být užitečné pochopit koncepční model, který je základem těchto rozhraní API. Tady jsou popsané klíčové koncepty.
Pokud DirectWrite provede skutečné rozložení nebo vykreslování textu, potřebuje přístup k skutečným datům písma. Objekt řezu písma obsahuje skutečná data písma, která musí existovat v místním systému. U jiných operací, jako je například kontrola dostupnosti konkrétního písma nebo prezentace voleb písem uživateli, je potřeba použít odkaz na konkrétní písmo, nikoli samotná data písma. V režimu DirectWrite obsahuje objekt odkazu na obličej písma pouze informace potřebné k vyhledání a vytvoření instance písma. Vzhledem k tomu, že odkaz na řez písma neobsahuje skutečná data, může DirectWrite pracovat s odkazy na rozpoznávání tváře písma, pro které jsou skutečná data ve vzdáleném síťovém umístění a také v případě, že jsou skutečná data místní.
Sada písem je sada odkazů na obličej písma spolu s určitými základními informačními vlastnostmi, které lze použít při odkazování na písmo nebo při porovnání s jinými písmy, jako je jméno rodiny nebo hodnota tloušťky písma. Skutečná data pro různá písma můžou být místní nebo všechna mohou být vzdálená nebo nějaká směs.
Sadu písem lze použít k získání odpovídajícího objektu kolekce písem. Další podrobnosti najdete v části Sady písem a kolekce písem níže.
Rozhraní IDWriteFontSet poskytuje metody, které umožňují dotazování na hodnoty vlastností, jako je název rodiny nebo váha písma, nebo pro odkazy na rozpoznávání tváře písma, které odpovídají konkrétním hodnotám vlastnosti. Po filtrování podle konkrétního výběru lze získat instanci IDWriteFontFaceReference rozhraní s metodami pro stažení (pokud jsou skutečná data písma aktuálně vzdálená), pro získání odpovídajícího IDWriteFontFace3 objektu, který lze použít pro rozložení a vykreslování.
Rozhraní IDWriteFontFile je základem každého řezu písma nebo odkazu na řez písma. Představuje umístění souboru písma a má dvě komponenty: zavaděč souborů písem a klíč souboru písma. Zavaděč souborů písem (IDWriteFontFileLoader) slouží k otevření souboru v případě potřeby a vrací datový proud s daty (IDWriteFontFileStream). V závislosti na zavaděče můžou být data umístěná v místní cestě k souboru, vzdálené adrese URL nebo v vyrovnávací paměti. Klíč je hodnota definovaná zavaděčem, která jednoznačně identifikuje soubor v kontextu zavaděče, což zavaděči umožňuje vyhledat data a vytvořit pro něj datový proud.
Vlastní písma je možné snadno přidat do vlastní sady písem, která se pak dají použít k filtrování nebo uspořádání informací o písmech pro účely, jako je například vytvoření uživatelského rozhraní pro výběr písma. Sadu písem lze použít také k vytvoření kolekce písem pro použití v rozhraních API vyšší úrovně, jako je IDWriteTextFormat a IDWriteTextLayout. Rozhraní IDWriteFontSetBuilder lze použít k vytvoření vlastní sady písem, která obsahuje několik vlastních písem. Lze jej také použít k vytvoření vlastní sady písem, která kombinuje vlastní písma a systémová písma; nebo kombinuje písma s různými zdroji pro skutečná data – místní úložiště, vzdálené adresy URL a paměť.
Jak už bylo zmíněno, odkaz na řez písma může odkazovat na data písma ve vzdáleném zdroji, ale data musí být místní, aby bylo možné získat objekt pro rozpoznávání tváře písma, který lze použít k rozložení a vykreslování. Stahování vzdálených dat zpracovává fronta stahování písem. Aplikace mohou použít rozhraní IDWriteFontDownloadQueue k zařazení požadavků na stažení vzdálených písem, aby zahájily proces stahování, a zaregistrovat IDWriteFontDownloadListener objekt, který provede akci po dokončení procesu stahování.
Pro většinu zde popsaných rozhraní poskytuje DirectWrite systémové implementace. Jedinou výjimkou je rozhraní IDWriteFontDownloadListener, které aplikace implementuje k provádění akcí specifických pro aplikaci, pokud byla vzdálená písma stažena místně. Aplikace můžou mít důvod poskytovat vlastní implementace pro určitá další rozhraní, i když by to bylo potřeba jenom v konkrétních pokročilejších scénářích. Aplikace by například potřebovala poskytnout vlastní implementaci rozhraní IDWriteFontFileLoader pro zpracování souborů písem v místním úložišti, které používají formát kontejneru WOFF2. Další podrobnosti najdete níže.
Písma a formáty souborů písem
Dalším klíčovým konceptem, který je užitečný k pochopení, je vztah mezi jednotlivými řezy písma a soubory písem, které je obsahují. Znalost souboru písma OpenType (.ttf nebo .otf) obsahujícího jedno písmo Formát písma OpenType ale umožňuje také kolekci písem OpenType (.ttc nebo .otc), což je jeden soubor, který obsahuje více písem. Soubory OpenType Collection se často používají pro velká písma, která úzce souvisejí a mají stejné hodnoty pro určitá data písma: kombinací písem v jednom souboru je možné běžná data zrušit. Z tohoto důvodu musí odkaz na řez písma nebo řez písma odkazovat nejen na soubor písma (nebo ekvivalentní zdroj dat), ale musí také v tomto souboru zadat index písma, pro obecný případ, ve kterém může být soubor kolekce.
U písem používaných na webu jsou data písem často zabalená do určitých formátů kontejnerů, WOFF nebo WOFF2, které poskytují určitou kompresi dat písem a určitou úroveň ochrany před pirátstvím a porušením licencí písem. Funkčně je soubor WOFF nebo WOFF2 ekvivalentní písmu OpenType nebo souboru kolekce písem, ale data jsou kódována v jiném formátu, který vyžaduje rozbalení před jejich použití.
Některá rozhraní API DirectWrite můžou řešit jednotlivé řezy písem, zatímco jiná rozhraní API můžou zpracovávat soubory, které mohou obsahovat soubory kolekce OpenType, které obsahují více tváří. Podobně určitá rozhraní API zpracovávají pouze nezpracovaná data ve formátu OpenType, zatímco jiná rozhraní API můžou zpracovávat zabalené formáty kontejnerů WOFF a WOFF2. Tyto podrobnosti jsou uvedeny v diskuzi níže.
Sady písem a kolekce písem
Některé aplikace mohou být implementovány pro práci s písmy pomocí rozhraní IDWriteFontCollection. Mezi kolekcí písem a sadou písem existuje přímá korespondence. Každá z nich může obsahovat stejná písma, ale prezentuje je v jiné organizaci. Z jakékoli kolekce písem lze získat odpovídající sadu písem a naopak.
Při práci s řadou vlastních písem je nejjednodušší použít rozhraní tvůrce sady písem k vytvoření vlastní sady písem a po vytvoření sady písem získat kolekci písem. Postup vytvoření vlastní sady písem bude podrobně popsán níže. K získání IDWriteFontCollection1 rozhraní ze sady písem, IDWriteFactory3::CreateFontCollectionFromFontSet metoda.
Pokud má aplikace objekt kolekce a potřebuje získat odpovídající sadu písem, lze to provést pomocí IDWriteFontCollection1::GetFontSet metoda.
Běžné scénáře
Tato část popisuje některé z nejběžnějších scénářů zahrnujících vlastní sady písem:
- Vytvoření vlastní sady písem pomocí libovolných písem na cestách v místním systému souborů
- Vytvoření vlastní sady písem s použitím známých písem (možná zkompilovaných s aplikací), která jsou uložená v místním systému souborů.
- Vytvoření vlastní sady písem pomocí známých vzdálených písem na webu
- Vytvoření vlastní sady písem pomocí dat písem načtených do paměti
Kompletní implementace pro tyto scénáře jsou k dispozici v DirectWrite Custom Font Sets ukázka. Tato ukázka také ukazuje jeden pokročilejší scénář pro zpracování dat písem zabalených ve formátech kontejnerů WOFF nebo WOFF2, které si probereme níže.
Vytvoření sady písem pomocí libovolných písem v místním systému souborů
Při práci s libovolnou sadou souborů písem v místním úložišti je IDWriteFontSetBuilder1::AddFontFile metoda vhodná, protože v jednom volání dokáže zpracovat všechny tváře písma v souboru OpenType Font Collection a také všechny instance pro písmo proměnné OpenType. Tato možnost je dostupná ve Windows 10 Creators Update (preview build 15021 nebo novější) a doporučuje se, kdykoli je k dispozici.
Chcete-li použít tuto metodu, použijte následující proces.
- 1. Začněte vytvořením rozhraní IDWriteFactory5:
- Pro každý soubor písma v místním systému souborů vytvořte IDWriteFontFile, který na něj odkazuje:
- Po přidání všech souborů do tvůrce sady písem je možné vytvořit vlastní sadu písem:
IDWriteFactory5* pDWriteFactory;
HRESULT hr = DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory5),
reinterpret_cast<IUnknown**>(&pDWriteFactory)
);
2. Pomocí továrny získat IDWriteFontSetBuilder1 rozhraní:
IDWriteFontSetBuilder1* pFontSetBuilder;
if (SUCCEEDED(hr))
{
hr = pDWriteFactory->CreateFontSetBuilder(&pFontSetBuilder);
}
IDWriteFontFile* pFontFile;
if (SUCCEEDED(hr))
{
hr = pDWriteFactory->CreateFontFileReference(pFilePath, /* lastWriteTime*/ nullptr, &pFontFile);
}
4. Přidejte objekt IDWriteFontFile do tvůrce sady písem pomocí metody AddFontFile:
hr = pFontSetBuilder->AddFontFile(pFontFile);
Pokud cesta k souboru zadaná ve volání CreateFontFileReference odkazovat na něco jiného než podporovaný soubor OpenType, volání AddFontFile vrátí chybu, DWRITE_E_FILEFORMAT.
IDWriteFontSet* pFontSet;
hr = pFontSetBuilder->CreateFontSet(&pFontSet);
Pokud aplikace musí běžet ve verzích Windows 10 starších než Windows 10 Creators Update, metoda AddFontFile nebude dostupná. Dostupnost lze zjistit vytvořením rozhraní IDWriteFactory3 a následným použitím queryInterface k pokusu o získání rozhraní IDWriteFactory5: pokud to bude úspěšné, bude k dispozici také IDWriteFontSetBuilder1 rozhraní a AddFontFile metoda.
Pokud metoda AddFontFile není k dispozici, pak IDWriteFontSetBuilder::AddFontFaceReference metoda musí být použita k přidání jednotlivých řezů písma. Chcete-li povolit soubory Kolekce písem OpenType, které obsahují více tváří, lze k určení počtu tváří obsažených v souboru použít metodu IDWriteFontFile::Analyze. Proces je následující.
- 1. Začněte vytvořením rozhraní IDWriteFactory3:
- Pomocí továrny získejte rozhraní IDWriteFontSetBuilder:
- Pro každý soubor písma vytvořte IDWriteFontFile, jak je uvedeno výše:
- Po přidání všech tváří do tvůrce sady písem vytvořte vlastní sadu písem, jak je znázorněno výše.
IDWriteFactory3* pDWriteFactory;
HRESULT hr = DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory5),
reinterpret_cast<IUnknown**>(&pDWriteFactory)
);
IDWriteFontSetBuilder* pFontSetBuilder;
if (SUCCEEDED(hr))
{
hr = pDWriteFactory->CreateFontSetBuilder(&pFontSetBuilder);
}
IDWriteFontFile* pFontFile;
if (SUCCEEDED(hr))
{
hr = pDWriteFactory->CreateFontFileReference(pFilePath, /* lastWriteTime*/ nullptr, &pFontFile);
}
Místo přidání souboru přímo do tvůrce sady písem musíme určit počet tváří a vytvořit individuální IDWriteFontFaceReference objekty.
4. Pomocí metody Analyzovat získejte počet tváří v souboru.
BOOL isSupported;
DWRITE_FONT_FILE_TYPE fileType;
UINT32 numberOfFonts;
hr = pFontFile->Analyze(&isSupported, &fileType, /* face type */ nullptr, &numberOfFonts);
Metoda Analyze také nastaví hodnoty parametrů isSupported a fileType. Pokud soubor není podporovaným formátem, bude isSupported FALSE a je možné provést příslušnou akci, například ignorování souboru.
5. Smyčkujte počet písem nastavených v parametru numberOfFonts. Ve smyčce vytvořte IDWriteFontFaceReference pro každou dvojici souborů a indexů a přidejte ji do tvůrce sady písem.
for (uint32_t fontIndex = 0; fontIndex < numberOfFonts; fontIndex++)
{
IDWriteFontFaceReference* pFontFaceReference;
hr = pDWriteFactory->CreateFontFaceReference(pFontFile, fontIndex, DWRITE_FONT_SIMULATIONS_NONE, &pFontFaceReference);
if (SUCCEEDED(hr))
{
hr = pFontSetBuilder->AddFontFaceReference(pFontFaceReference);
}
}
Aplikaci je možné navrhnout tak, aby při spouštění ve Windows 10 Creators Update používala upřednostňovanou metodu AddFontFile, ale při spuštění ve starších verzích Windows 10 se vrátíme k použití metody AddFontFaceReference. Otestujte dostupnost rozhraní IDWriteFactory5, jak je popsáno výše, a odpovídajícím způsobem větvení. Tento přístup je znázorněn v ukázce vlastních sad písem DirectWrite.
Vytvoření sady písem pomocí známých písem v místním systému souborů
Jak je uvedeno výše, každý odkaz na obličej v sadě písem je přidružený k určitým informačním vlastnostem, jako je název rodiny a váha písma. Při přidání vlastních písem do tvůrce sady písem pomocí výše uvedených volání rozhraní API se tyto informační vlastnosti získávají přímo ze skutečných dat písma, která se čtou při přidávání písma. V některých situacích ale aplikace má jiný zdroj informací o písmu, může chtít pro tyto vlastnosti zadat vlastní hodnoty.
Jako příklad, jak to může být užitečné, předpokládejme, že aplikace sbalí některá písma, která se používají k prezentaci konkrétních prvků uživatelského rozhraní v aplikaci. Někdy, například s novou verzí aplikace, může být potřeba změnit konkrétní písma, která aplikace používá pro tyto prvky. Pokud aplikace zakódovala odkazy na konkrétní písma, bude nahrazení jednoho písma vyžadovat změnu každého z těchto odkazů. Místo toho, pokud aplikace používá vlastní vlastnosti k přiřazení funkčních aliasů na základě typu prvku nebo textu, který se vykresluje, mapuje každý alias na konkrétní písmo na jednom místě a potom používá aliasy ve všech kontextech, kde se písma vytvářejí a manipulují, pak nahrazení jednoho písma jiným vyžaduje změnu pouze jednoho místa, kde je alias namapován na konkrétní písmo.
Vlastní hodnoty pro informační vlastnosti lze přiřadit při IDWriteFontSetBuilder::AddFontFaceReference metoda je volána. Metoda, jak to udělat, je následující; můžete ho použít v libovolné verzi Windows 10.
Jak je znázorněno výše, začněte získáním IDWriteFactory3 a IDWriteFontSet rozhraní. Pro každý vlastní řez písma, který chcete přidat, vytvořte IDWriteFontFaceReference, jak je znázorněno výše. Před tím, než se přidá do tvůrce sady písem (ve smyčce v kroku 5 výše), ale aplikace definuje hodnoty vlastních vlastností, které se mají použít.
Sada hodnot vlastních vlastností je definována pomocí pole DWRITE_FONT_PROPERTY struktur. Každá z těchto vlastností identifikuje konkrétní vlastnost z výčtu DWRITE_FONT_PROPERTY_ID a odpovídající hodnotu vlastnosti, která se má použít.
Všimněte si, že všechny hodnoty vlastností jsou přiřazeny jako řetězce. Pokud se tyto hodnoty můžou později zobrazit uživatelům, můžou být nastaveny alternativní hodnoty pro danou vlastnost pro různé jazyky, ale není to povinné. Všimněte si také, že pokud aplikace nastaví hodnoty vlastních vlastností, budou použity pouze ty hodnoty, které jsou zadány v sadě Písem; DirectWrite nebude odvozovat žádné hodnoty přímo z písma pro informační vlastnosti použité v sadě písem.
Následující příklad definuje vlastní hodnoty pro tři informační vlastnosti: název rodiny, celé jméno a váha písma.
DWRITE_FONT_PROPERTY props[] =
{
{ DWRITE_FONT_PROPERTY_ID_FAMILY_NAME, L"My Icon Font", L"en-US" },
{ DWRITE_FONT_PROPERTY_ID_FULL_NAME, L"My Icon Font", L"en-US" },
{ DWRITE_FONT_PROPERTY_ID_WEIGHT, L"400", nullptr }
};
Po definování požadovaného pole hodnot vlastností pro písmo proveďte volání AddFontFaceRefence, předání pole vlastností a také odkaz na rozpoznávání tváře písma.
hr = pFontSetBuilder->AddFontFaceReference(pFontFaceReference, props, ARRAYSIZE(props));
Po přidání všech vlastních řezů písem do tvůrce sady písem spolu s vlastními vlastnostmi vytvořte vlastní sadu písem, jak je znázorněno výše.
Vytvoření vlastní sady písem pomocí známých vzdálených písem na webu
Vlastní vlastnosti jsou důležité pro práci se vzdálenými písmy. Každý odkaz na rozpoznávání tváře písma musí mít některé informační vlastnosti, které charakterizují písmo a odlišují ho od jiných písem. Vzhledem k tomu, že data písma pro vzdálená písma nejsou místní, directWrite nemůže odvodit vlastnosti přímo z dat písma. Proto musí být vlastnosti explicitně zadány při přidávání vzdáleného písma do tvůrce sady písem.
Posloupnost volání rozhraní API pro přidání vzdálených písem do sady písem je podobná sekvenci popsané v předchozím scénáři. Vzhledem k tomu, že jsou data písma vzdálená, budou se ale operace související se čtením skutečných dat písma lišit od práce se soubory v místním úložišti. Pro tuto situaci se do Windows 10 Creators Update přidalo nové rozhraní nižší úrovně IDWriteRemoteFontFileLoader.
Chcete-li použít zavaděč vzdáleného souboru písma, musí být nejprve zaregistrován v objektu pro vytváření DirectWrite. Zavaděč bude muset aplikace uchovávat, dokud se budou používat písma přidružená k aplikaci. Jakmile se písma už nepoužívají a v určitém okamžiku před zničením továrny musí být zavaděč neregistrovaný. To lze provést v destruktoru pro třídu, která vlastní zavaděč objektu. Tyto kroky se zobrazí níže.
Metoda vytvoření vlastní sady písem pomocí vzdálených písem je následující; to vyžaduje Windows 10 Creators Update.
- 1. Vytvořte rozhraní IDWriteFactory5, jak je znázorněno výše.
2. Vytvořte IDWriteFontSetBuilder rozhraní, jak je znázorněno výše.
3. Pomocí továrny získat IDWriteRemoteFontFileLoader.
- Definujte vlastní vlastnosti pro řez písma, jak je znázorněno výše.
- Přidejte odkaz na řez písma spolu s vlastními vlastnostmi do tvůrce sady písem, jak je znázorněno výše.
- Po přidání všech písem do tvůrce sady písem vytvořte sadu písem, jak je znázorněno výše.
- V určitém okamžiku, kdy se vzdálená písma už nebudou používat, zrušíte registraci vzdáleného zavaděče souborů písem.
IDWriteRemoteFontFileLoader* pRemoteFontFileLoader;
if (SUCCEEDED(hr))
{
hr = pDWriteFactory->CreateHttpFontFileLoader(
/* referrerURL */ nullptr,
/* extraHeaders */ nullptr,
&pRemoteFontFileLoader
);
}
Vrátí systémovou implementaci vzdáleného rozhraní zavaděče písem, které dokáže zpracovávat interakce HTTP pro stahování dat písem jménem aplikace. V případě potřeby služby písem nebo služeb, které jsou zdrojem písem, je možné zadat adresu URL refereru nebo další hlavičky.
Důležitý
Poznámka k zabezpečení: Při pokusu o načtení vzdáleného písma může útočník zodpovědět zamýšlený server, který bude volána. V takovém případě by se útočníkovi zobrazily adresy URL cílového a referreru a podrobnosti hlavičky. Vývojáři aplikací zodpovídají za zmírnění tohoto rizika. Místo protokolu HTTP se doporučuje použít protokol HTTPS.
Jeden zavaděč souborů vzdáleného písma lze použít pro více písem, i když se dají použít různé zavaděče, pokud jsou písma získána z více služeb, které mají různé požadavky na adresu URL refereru nebo další hlavičky.
4. Zaregistrujte zavaděč souborů vzdáleného písma ve službě Factory.
if (SUCCEEDED(hr))
{
hr = pDWriteFactory->RegisterFontFileLoader(pRemoteFontFileLoader);
}
Od tohoto okamžiku jsou kroky pro vytvoření vlastní sady písem podobné krokům popsaným pro známé místní soubory písem se dvěma důležitými výjimkami. Za prvé, IDWriteFontFile objekt je vytvořen pomocí vzdáleného rozhraní zavaděče písem místo použití továrny. Za druhé, Metodu Analyze nelze použít, protože data písma nejsou místní. Místo toho musí aplikace vědět, jestli je vzdáleným souborem písem OpenType Font Collection, a pokud ano, musí vědět, která písma v kolekci bude používat, a index pro každou z nich. Zbývající kroky jsou tedy následující.
5. Pro každý vzdálený soubor písma použijte rozhraní zavaděče vzdáleného písma k vytvoření IDWriteFontFile, zadejte adresu URL potřebnou pro přístup k souboru písma.
IDWriteFontFile* pFontFile;
hr = pRemoteFontFileLoader->CreateFontFileReferenceFromUrl(
pDWriteFactory,
/* baseUrl */ L"https://github.com/",
/* fontFileUrl */ L"winjs/winjs/blob/master/src/fonts/Symbols.ttf?raw=true",
&pFontFile
);
Všimněte si, že úplnou adresu URL je možné zadat v parametru fontFileUrl nebo ji lze rozdělit na základní a relativní části. Pokud je zadaná základní adresa URL, pak zřetězení hodnot baseUrl a fontFileUrl musí poskytnout úplnou adresu URL – DirectWrite nezadá žádné další oddělovače.
Důležitý
Zabezpečení / výkon poznámka: Při pokusu o načtení vzdáleného písma neexistuje žádná záruka, že Systém Windows obdrží odpověď ze serveru. V některých případech může server odpovědět chybou typu soubor nenalezena pro neplatnou relativní adresu URL, ale přestane reagovat, pokud obdrží více neplatných požadavků. Pokud server nereaguje, systém Windows nakonec vyprší časový limit, ale pokud se zahájí více načtení, může to trvat několik minut. Měli byste udělat, co můžete udělat, abyste zajistili, že adresy URL budou platné při volání.
Všimněte si také, že adresa URL může odkazovat na nezpracovaný soubor písma OpenType (.ttf, .otf, .ttc, .otc), ale může také odkazovat na písma v souboru kontejneru WOFF nebo WOFF2. Pokud se odkazuje na soubor WOFF nebo WOFF2, pak implementace DirectWrite vzdáleného zavaděče souborů písem automaticky rozbalí data písma ze souboru kontejneru.
6. Pro každý index řezu písma v souboru vzdáleného písma, který se má použít, vytvořte IDWriteFontFaceReference.
IDWriteFontFaceReference* pFontFaceReference;
hr = pDWriteFactory->CreateFontFaceReference(pFontFile, /* faceIndex */ 0, DWRITE_FONT_SIMULATIONS_NONE, &pFontFaceReference);
hr = pDWriteFactory->UnregisterFontFileLoader(pRemoteFontFileLoader);
Po vytvoření vlastní sady písem s vlastními vzdálenými písmy obsahuje sada písem odkazy a informační vlastnosti vzdálených písem, ale skutečná data jsou stále vzdálená. Podpora technologie DirectWrite pro vzdálená písma umožňuje zachovat odkaz na řez písma v sadě písem a pro výběr písma pro použití v rozložení a vykreslování, ale že skutečná data se nestáhnou, dokud nebude potřeba ho skutečně použít, například při provádění rozložení textu.
Aplikace může využít předem nastavený přístup tím, že požádá o stažení dat písma DirectWrite a pak čeká na potvrzení úspěšného stažení před zahájením zpracování s písmem. Stahování sítě ale znamená určitou latenci nepředvídatelné doby trvání a úspěch je také nejistý. Z tohoto důvodu bude obvykle lepší použít jiný přístup, což umožňuje provádět rozložení a vykreslování na začátku pomocí alternativních nebo záložních písem, která jsou již místní, a současně požadovat stažení požadovaného vzdáleného písma a potom aktualizovat výsledky po stažení požadovaného písma.
Chcete-li požádat o stažení celého písma před jeho použití, lze použít metodu IDWriteFontFaceReference::EnqueueFontDownloadRequest metoda. Pokud je písmo velmi velké, může být ke zpracování konkrétních řetězců potřeba jenom část dat. DirectWrite poskytuje další metody, které lze použít k vyžádání částí dat písma potřebných pro konkrétní obsah, EnqueueCharacterDownloadRequest a EnqueueGlyphDownloadRequest.
Předpokládejme, že přístup, který se má v aplikaci provést, je umožnit počáteční zpracování pomocí místních, alternativních nebo náhradních písem. Metodu IDWriteFontFallback::MapCharacters lze použít k identifikaci místních záložních písem a také automaticky zapíše požadavek na stažení upřednostňovaného písma. Pokud se používá IDWriteTextLayout a některé nebo všechny texty v rozložení jsou formátovány pomocí vzdáleného odkazu na písmo, DirectWrite automaticky použije MapCharacters metodu k získání místních záložních písem a vytvoření fronty požadavku na stažení vzdálených dat písma.
DirectWrite udržuje frontu pro stahování písem pro každou továrnu a požadavky provedené pomocí výše uvedených metod se do této fronty přidají. Frontu pro stahování písem lze získat pomocí metody IDWriteFactory3::GetFontDownloadQueue.
Pokud se vytvoří žádost o stažení, ale data písma jsou již místní, výsledkem bude no-op: Do fronty pro stahování se nic nedají přidat. Aplikace může zkontrolovat, zda je fronta prázdná nebo čekají na stažení požadavky voláním IDWriteFontDownloadQueue::IsEmpty metoda.
Po přidání vzdálených požadavků na písmo do fronty se musí zahájit proces stahování. Při použití vzdálených písem v IDWriteTextLayout, stahování se spustí automaticky, když aplikace volá IDWriteTextLayout metody, které vynucují operace rozložení nebo vykreslování, například GetLineMetrics nebo Draw metody. V jiných scénářích musí aplikace zahájit stahování přímo voláním IDWriteFontDownloadQueue::BeginDownload.
Po dokončení stahování bude aplikace až do aplikace, která provede příslušné akce – pokračování v čekajících operacích nebo opakování operací, které byly provedeny na začátku s záložními písmy. (Pokud se používá rozložení textu DirectWrite, IDWriteTextLayout3::InvalidateLayout lze použít k vymazání dočasných výsledků vypočítaných pomocí záložních písem.) Aby aplikace mohla být upozorněna, když se proces stahování dokončí a provede příslušné akce, musí aplikace poskytnout implementaci IDWriteFontDownloadListener rozhraní a předat ji do volání BeginDownload.
Důležitý
Zabezpečení / výkon poznámka: Při pokusu o načtení vzdáleného písma neexistuje žádná záruka, že Systém Windows obdrží odpověď ze serveru. Pokud server nereaguje, systém Windows nakonec vyprší časový limit, ale může to trvat několik minut, pokud se načítá více vzdálených písem, ale selhává. Volání BeginDownload se vrátí okamžitě. Aplikace by při čekání na IDWriteFontDownloadListener::D ownloadCompleted neměli blokovat uživatelské rozhraní.
Ukázkové implementace těchto interakcí s frontou pro stahování písem DirectWrite a rozhraním IDWriteFontDownloadListener rozhraní lze vidět v ukázce DirectWrite Custom Font Setsa také v ukázce DirectWrite Písma ke stažení.
Vytvoření vlastní sady písem pomocí dat písem načtených do paměti
Stejně jako operace nízké úrovně pro čtení dat ze souboru písma se liší u souborů na místním disku a vzdálených souborů na webu, totéž platí i pro data písma načtená do vyrovnávací paměti. V systému Windows 10 Creators Update idWriteInMemoryFontFileLoaderbylo přidáno nové rozhraní nízké úrovně pro zpracování dat písma v paměti.
Stejně jako u zavaděče vzdáleného souboru písma musí být zavaděč souborů písem v paměti nejprve zaregistrován v továrně DirectWrite. Zavaděč bude muset aplikace uchovávat, dokud se budou používat písma přidružená k aplikaci. Jakmile se písma už nepoužívají a v určitém okamžiku před zničením továrny musí být zavaděč neregistrovaný. To lze provést v destruktoru pro třídu, která vlastní zavaděč objektu. Tyto kroky se zobrazí níže.
Pokud aplikace obsahuje samostatné informace o řezech písma reprezentovaných daty, může do tvůrce sady písem přidat odkazy na jednotlivé řezy písma se zadanými vlastními vlastnostmi. Vzhledem k tomu, že data písma jsou v místní paměti, není to však nutné; DirectWrite bude moci číst data přímo k odvození hodnot vlastnosti.
DirectWrite předpokládá, že data písma jsou v nezpracovaných formátech OpenType, což odpovídá souboru OpenType (.ttf, .otf, .ttc, .otc), ale v paměti, nikoli na disku. Data nemohou být ve formátu kontejneru WOFF nebo WOFF2. Data mohou představovat kolekci písem OpenType. Pokud se nepoužívají vlastní vlastnosti, lze IDWriteFontSetBuilder1::AddFontFile metodu použít k přidání všech řezů písma do dat v jednom volání.
Důležitým aspektem scénáře v paměti je životnost dat. Pokud je ukazatel na vyrovnávací paměť poskytnut directWrite bez jasného označení, že existuje vlastník, DirectWrite vytvoří kopii dat do nové vyrovnávací paměti, kterou bude vlastnit. Aby se zabránilo kopírování dat a další přidělení paměti, může aplikace předat objekt vlastníka dat, který implementuje IUnknown a který vlastní vyrovnávací paměť obsahující data písma. Implementací tohoto rozhraní může DirectWrite přidat do počtu odkazů objektu, čímž zajistí životnost vlastněných dat.
Metoda vytvoření vlastní sady písem pomocí dat písem v paměti je následující; to vyžaduje Windows 10 Creators Update. To bude předpokládat objekt vlastníka dat implementovaný aplikací, který implementuje IUnknown a také metody, které vrací ukazatel na vyrovnávací paměť a velikost vyrovnávací paměti.
- 1. Vytvořte rozhraní IDWriteFactory5, jak je znázorněno výše.
2. Vytvořte rozhraní [**IDWriteFontSetBuilder1**](/windows/win32/api/dwrite_3/nn-dwrite_3-idwritefontsetbuilder1), jak je znázorněno výše.
3. Použijte továrnu k získání IDWriteInMemoryFontFileLoader.
IDWriteInMemoryFontFileLoader* pInMemoryFontFileLoader;
if (SUCCEEDED(hr))
{
hr = pDWriteFactory->CreateInMemoryFontFileLoader(&pInMemoryFontFileLoader);
}
Vrátí systémovou implementaci rozhraní zavaděče písem v paměti.
4. Zaregistrujte zavaděč písem v paměti v továrně.
if (SUCCEEDED(hr))
{
hr = pDWriteFactory->RegisterFontFileLoader(pInMemoryFontFileLoader);
}
5. Pro každý soubor písma v paměti použijte zavaděč písem v paměti k vytvoření IDWriteFontFile.
IDWriteFontFile* pFontFile;
hr = pInMemoryFontFileLoader->CreateInMemoryFontFileReference(
pDWriteFactory,
pFontDataOwner->fontData /* returns void* */,
pFontDataOwner->fontDataSize /* returns UINT32 */,
pFontDataOwner /* ownerObject, owns the memory with font data and implements IUnknown */,
&pFontFile
);
6. Přidejte objekt IDWriteFontFile do tvůrce sady písem pomocí metody AddFontFile, jak je znázorněno výše. Pokud je potřeba, aplikace může místo toho vytvořit jednotlivé IDWriteFontFaceReference objekty založené na IDWriteFontFile, volitelně definovat vlastní vlastnosti pro každý odkaz na řez písma a pak přidat odkaz na řez písma s vlastními vlastnostmi do sady písem pomocí AddFontFaceReference metoda, jak je znázorněno výše.
7. Po přidání všech písem do tvůrce sady písem vytvořte vlastní sadu písem, jak je znázorněno výše.
8. V určitém okamžiku, kdy už nebudou použita písma v paměti, odregistrujte zavaděč souborů písem v paměti.
hr = pDWriteFactory->UnregisterFontFileLoader(pInMemoryFontFileLoader);
Pokročilé scénáře
Některé aplikace můžou mít zvláštní požadavky, které vyžadují pokročilejší zpracování, než je popsáno výše.
Kombinování sad písem
Některé aplikace můžou potřebovat vytvořit sadu písem, která obsahuje některé kombinace položek z jiných sad písem. Aplikace může například chtít vytvořit sadu písem, která kombinuje všechna písma nainstalovaná v systému s výběrem vlastních písem nebo kombinuje nainstalovaná písma odpovídající určitým kritériím s jinými písmy. DirectWrite má rozhraní API pro podporu manipulace a kombinování sad písem.
Pokud chcete zkombinovat dvě nebo více sad písem, IDWriteFontSetBuilder::AddFontSet metoda přidá všechna písma v dané sadě písem, která se mají přidat do tvůrce sad písem v jednom volání. Pokud jsou v nové sadě písem vyžadována pouze určitá písma z existující sady písem, lze IDWriteFontSet::GetMatchingFonts metodu odvodit nový objekt sady písem, který byl filtrován tak, aby obsahoval pouze písma odpovídající zadaným vlastnostem. Tyto metody poskytují snadný způsob, jak vytvořit vlastní sadu písem, která kombinuje písma ze dvou nebo více existujících sad písem.
Použití místních dat písma WOFF nebo WOFF2
Pokud má aplikace soubory písem v místním systému souborů nebo v vyrovnávací paměti, ale používají formáty kontejnerů WOFF nebo WOFF2, DirectWrite (Windows 10 Creator Update nebo novější) poskytuje metodu pro rozbalení formátu kontejneru, IDWriteFactory5::UnpackFontFile, který vrátí IDWriteFontFileStream.
Aplikace však bude potřebovat způsob, jak získat IDWriteFontFileStream do objektu zavaděče souboru písma. Jedním ze způsobů, jak to udělat, je vytvořit vlastní IDWriteFontFileLoader implementaci, která zabalí stream. Stejně jako u jiných zavaděčů písem je nutné ho před použitím zaregistrovat a zrušit registraci, než továrna přejde mimo rozsah.
Pokud se vlastní zavaděč použije také s nezpracovanými (nezabalenými) soubory písem, aplikace by také potřebovala poskytnout vlastní implementaci IDWriteFontFileStream rozhraní pro zpracování těchto souborů. Existují jednodušší způsoby, jak používat rozhraní API popisovaná výše pro zpracování nezpracovaných souborů písem. Potřeba vlastní implementace datového proudu se může vyhnout použitím samostatných cest kódu pro zabalené soubory písem a nezpracovaných souborů písem.
Po vytvoření vlastního objektu zavaděče souborů písem se do zavaděče přidají data souboru s zabaleným písmem do zavaděče pomocí prostředků specifických pro aplikaci. Zavaděč dokáže zpracovat více souborů písem, z nichž každý je identifikován pomocí klíče definovaného aplikací, který je neprůhlený pro DirectWrite. Po přidání souboru s zabaleným písmem do zavaděče se metoda IDWriteFactory::CreateCustomFontFileReference použije k získání IDWriteFontFile na základě daného zavaděče pro data písma identifikovaná daným klíčem.
Skutečné rozbalení dat písma lze provést, protože písma jsou přidána do zavaděče, ale lze je také zpracovat v IDWriteFontFileLoader::CreateStreamFromKey metoda, která DirectWrite zavolá při prvním čtení dat písma.
Po vytvoření objektu IDWriteFontFile budou zbývající kroky pro přidání písem do vlastní sady písem popsané výše.
Implementace využívající tento přístup je znázorněna v ukázce DirectWrite Custom Font Sets.
Použití mechanismů vzdáleného písma DirectWrite s vlastní implementací sítě nízké úrovně
Mechanismy DirectWrite pro zpracování vzdálených písem je možné rozdělit do mechanismů vyšší úrovně – sady písem, které obsahují odkazy na rozpoznávání písma pro vzdálená písma, kontrolu umístění dat písem a správu fronty pro žádosti o stahování písem – a mechanismy nižší úrovně, které zpracovávají skutečné stahování. Některé aplikace můžou chtít využívat mechanismy vzdáleného písma vyšší úrovně, ale také vyžadují vlastní síťové interakce, například komunikaci se servery pomocí jiných protokolů než HTTP.
V takovém případě bude aplikace muset vytvořit vlastní implementaci IDWriteRemoteFontFileLoader rozhraní, které interaguje s jinými rozhraními nižší úrovně požadovanými způsoby. Aplikace bude také muset poskytovat vlastní implementace těchto rozhraní nižší úrovně: IDWriteRemoteFontFileStreama IDWriteAsyncResult. Tato tři rozhraní mají metody zpětného volání, které DirectWrite bude volat během operací stahování.
Při IDWriteFontDownloadQueue::BeginDownload je volána technologie DirectWrite provede dotazy na vzdálený zavaděč souborů písem o umístění dat a požádá vzdálený datový proud. Pokud data nejsou místní, zavolá metodu BeginDownload datového proudu. Implementace datového proudu by neměla u daného volání blokovat, ale měla by se okamžitě vrátit a předat zpět IDWriteAsyncResult objekt, který poskytuje obslužné rutiny čekání DirectWrite bude používat k čekání na asynchronní operaci stahování. Implementace vlastního datového proudu zodpovídá za zpracování vzdálené komunikace. Jakmile dojde k události dokončení, DirectWrite zavolá IDWriteAsyncResult::GetResult k určení výsledku operace. Pokud je výsledek úspěšný, očekává se, že následná volání ReadFragment do datového proudu pro stažené oblasti budou úspěšná.
Důležitý
Poznámka k zabezpečení a výkonu: Při pokusu o načtení vzdáleného písma existuje potenciál obecně pro útočníka falšování požadovaného serveru nebo že server nemusí reagovat. Pokud implementujete vlastní síťové interakce, můžete mít větší kontrolu nad zmírněním rizik než při práci se servery třetích stran. Je však na vás, abyste zvážili vhodná omezení rizik, aby se zabránilo zpřístupnění informací nebo odepření služby. Doporučuje se zabezpečené protokoly, jako je HTTPS. Měli byste také sestavit v určitém časovém limitu, aby se obslužný rutina události vrácená do DirectWrite nakonec nastavil.
Podpůrné scénáře ve starších verzích Windows
Popsané scénáře mohou být podporovány v DirectWrite ve starších verzích Windows, ale vyžadovaly by mnohem větší vlastní implementaci v části aplikace pomocí omezenějších rozhraní API, která byla k dispozici před Windows 10. Další informace najdete v tématu vlastních kolekcí písem (Windows 7/8).