Udostępnij za pośrednictwem


Czcionki zmiennych OpenType

W tym temacie opisano czcionki zmiennych OpenType, ich obsługę w trybie DirectWrite i Direct2D oraz sposób ich używania w aplikacji. 

Co to są czcionki zmiennych OpenType?

Wersja 1.8 specyfikacji formatu czcionki OpenType wprowadziła nowe rozszerzenie do formatu znanego jako odmian czcionek OpenType. Czcionki korzystające z tych rozszerzeń są nazywane czcionkami zmiennych OpenType. Czcionka zmiennej OpenType to pojedyncza czcionka, która może zachowywać się jak kilka czcionek przy użyciu ciągłej interpolacji między różnymi projektami, wszystkie zdefiniowane w ramach jednej czcionki.

Czcionka zmiennej OpenType może definiować ciągłe odmiany projektu wzdłuż co najmniej jednej niezależnej osi, takiej jak waga lub szerokość:

 

Wyświetla czcionkę zmiennej OpenType przy użyciu litery

Deweloper czcionek określa zestaw osi odmian do użycia w danej czcionki. Te osie mogą zawierać zestaw dobrze znanych osi (lub "zarejestrowanych") odmian, takich jak waga i szerokość, ale mogą również zawierać dowolne, niestandardowe osie odmiany zdefiniowane przez dewelopera czcionek.  

Wybierając zestaw osi odmian dla czcionki, deweloper czcionek definiuje abstrakcyjną, nwymiarową przestrzeń odmiany projektu dla czcionki. Aparaty tekstowe mogą określać potencjalnie dowolną pozycję lub "wystąpienie" w tym ciągłym obszarze do układania i renderowania tekstu. 

Deweloper czcionek może również wybrać i przypisać nazwy do określonych wystąpień w przestrzeni odmiany projektu; są one określane jako "nazwane wystąpienia". Na przykład czcionka z odmianą wagi może obsługiwać ciągłe zmiany między bardzo lekkimi i bardzo ciężkimi pociągnięciami, podczas gdy deweloper czcionek wybrał konkretne wagi wzdłuż tego kontinuum i przypisał im nazwy, takie jak "Light", "Regular" i "Semibold". 

Format czcionki zmiennej OpenType używa tabel danych znalezionych w tradycyjnych czcionkach OpenType oraz niektórych dodatkowych tabel, które opisują, w jaki sposób wartości różnych elementów danych zmieniają się dla różnych wystąpień. Format określa jedno wystąpienie odmiany jako "wystąpienie domyślne", które używa tradycyjnych tabel do pobierania wartości domyślnych. Wszystkie inne wystąpienia zależą od danych domyślnych i innych danych różnicowych. Na przykład tabela "glyf" może zawierać opis krzywej Beziera nominalnego kształtu glif, który jest kształtem używanym dla wystąpienia domyślnego, podczas gdy tabela "gvar" opisuje sposób dostosowania punktów kontrolnych beziera dla innych wystąpień. Podobnie inne wartości czcionek mogą mieć wartość nominalną oraz dane różnicowe opisujące zmianę tych wartości dla różnych wystąpień; na przykład x-height i inne metryki dla całej czcionki lub położenia zakotwiczenia znaczników specyficzne dla glyph i korekty kerningu. 

Ponieważ czcionki zmiennych mogą obsługiwać dowolny zestaw osi odmian, wymagają one rozszerzalnego modelu rodzin czcionek, który bardziej odzwierciedla sposób tworzenia rodzin czcionek: rodzina czcionek jest definiowana przez nazwę rodziny i pewne cechy projektowe, które są stałe, z dowolną liczbą (określoną przez dewelopera czcionek) sposobów, w jaki projekt może się różnić. Jedną rodzinę czcionek można utworzyć z wariantami wagi, ale można utworzyć inną rodzinę czcionek z wariantami x-height, serif-size, "funkiness" lub niezależnie od tego, co chce deweloper czcionek. W tym modelu wybór twarzy czcionki najlepiej opisuje się przy użyciu ogólnych lub "preferowanych" lub "typograficzne", nazwy rodziny oraz zestawu par klucz-wartość, z których każda reprezentuje rodzaj odmiany i konkretną wartość, z rodzajami odmian w ogóle jest rozszerzalnym zestawem. To ogólne pojęcie rodziny czcionek może dotyczyć tradycyjnych czcionek, niezwiązanych ze zmiennymi czcionkami, a także czcionek zmiennych. Na przykład w ramach tego ogólnego modelu rodziny typograficznej rodzina "Selawik VF" może mieć odmiany wagi, rozmiaru optycznego i serif projektu, z wystąpieniami takimi jak "Semilight Banner Sans". 

Niektóre istniejące implementacje oprogramowania, w tym istniejące interfejsy API DirectWrite, mogą jednak zostać zaprojektowane przy założeniu bardziej ograniczonego modelu rodzin czcionek. Na przykład niektóre aplikacje mogą zakładać, że rodzina czcionek może mieć co najwyżej warianty Regularne, Pogrubienie, Kursywa i Kursywa. Istniejące interfejsy IDWriteFontCollection i IDWriteFontFamily zakładają model rodziny wag/stretch/style ("WSS"), umożliwiając określenie wariantów w obrębie rodziny przy użyciu DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH lub DWRITE_FONT_STYLE wyliczenia jako parametrów. Biorąc pod uwagę poprzedni przykład, rozmiar optyczny i osie serif nie będą traktowane jako osie wewnętrzne rodziny odmian w modelu usług WSS. 

Pełna obsługa czcionek zmiennych wymaga interfejsów API, które umożliwiają określenie członka rodziny z potencjalnie kilkoma parametrami określonymi przez czcionkę. Jednak istniejące projekty interfejsów API mogą być w stanie zapewnić częściową obsługę czcionek zmiennych, projektując nazwane wystąpienia zdefiniowane w czcionki zmiennej w bardziej ograniczonych modelach rodziny czcionek. W poprzednim przykładzie "Selawik VF Semilight Banner Sans" można wyświetlić w modelu WSS jako "Selawik VF Banner Sans" rodziny z "Semilight" jako wariant wagi. 

W innym przykładzie rozważ rodzinę czcionek typograficznych, taką jak Sitka, z wariantami wagi i rozmiaru optycznego. Nazwane warianty w rodzinie obejmują Sitka Text Regular i Sitka Banner Bold (plus wiele innych). Nazwa rodziny typograficznej to "Sitka", a nazwy twarzy dla tych wariantów w modelu rodziny typograficznej to "Text Regular" i "Banner Bold". Modele rodziny czterech elementów członkowskich i WSS nie pozwalają na warianty rozmiarów optycznych w rodzinie, a więc różnice wielkości optycznej muszą być traktowane jak różnice na poziomie rodziny. W poniższej tabeli pokazano, jak wybór czcionek z rodziny typograficznej Sitka będzie traktowany w modelu rodziny WSS:

Model rodziny typograficznej

Model rodziny usług WSS

Rodzina

Twarz

Rodzina

Twarz

Sitka

Tekst — zwykły

Sitka Text

Regularny

Sitka

Baner pogrubiony

Baner Sitka

Śmiały

Sitka

Podpis kursywa

Podpis Sitka

Kursywa

 

Projekcja nazw z modelu rodziny typograficznej do modelu rodziny usług WSS może być stosowana do czcionek innych niż zmienne oraz do nazwanych wystąpień czcionek zmiennych. Nie można tego zrobić jednak w przypadku innych, nienazwanych wystąpień z przestrzeni ciągłej odmiany projektu czcionki zmiennej. Z tego powodu obsługa pełnej funkcjonalności czcionek zmiennych będzie wymagać interfejsów API przeznaczonych do odwołowywania się do twarzy w rodzinie typograficznej pod względem nieograniczonego zestawu osi odmian i wartości osi. 

Obsługa czcionek zmiennych OpenType w funkcji DirectWrite

Od wydania aktualizacji dla twórców systemu Windows 10 format czcionki zmiennej OpenType jest nadal bardzo nowy, a dostawcy czcionek, platformy i aplikacje są nadal w trakcie implementowania nowego formatu. Ta aktualizacja zapewnia początkową implementację tego formatu w funkcji DirectWrite. 

Elementy wewnętrzne DirectWrite zostały zaktualizowane w celu obsługi czcionek zmiennych OpenType. Korzystając z bieżących interfejsów API, zapewnia to obsługę wszystkich nazwanych wystąpień czcionki zmiennej. Ta obsługa może służyć do kompletnych przepływów pracy — od wyliczenia nazwanych wystąpień, wyboru nazwanego wystąpienia, użycia w układzie i kształtowaniu do renderowania i drukowania. Z korzyścią dla aplikacji, które również korzystają z międzyoperacyjności tekstu GDI dla niektórych operacji, podobna obsługa została również dodana w istniejących interfejsach API GDI. 

W aktualizacji Systemu Windows 10 Dla twórców funkcja DirectWrite nie obsługuje dowolnych wystąpień, które korzystają z funkcji ciągłej odmiany czcionek zmiennych.

W wielu operacjach zachowanie w funkcji DirectWrite nazwanych wystąpień czcionki zmiennej nie może odróżnić się od zachowania czcionek innych niż zmienne. Ponieważ obsługa jest zapewniana przy użyciu istniejących interfejsów API DirectWrite, nazwane wystąpienia czcionek zmiennych mogą nawet działać w wielu istniejących aplikacjach DirectWrite bez żadnych zmian. Wyjątki mogą jednak mieć zastosowanie w pewnych sytuacjach:

  • Jeśli aplikacja przetwarza dane czcionek bezpośrednio dla niektórych operacji. Jeśli na przykład aplikacja odczytuje dane konspektu glyph bezpośrednio z pliku czcionki w celu utworzenia pewnych efektów wizualnych.
  • Jeśli aplikacja używa biblioteki innej firmy na potrzeby niektórych operacji. Jeśli na przykład aplikacja używa funkcji DirectWrite dla układu, aby uzyskać końcowe indeksy i pozycje glifów, ale następnie używa biblioteki innej firmy do renderowania.
  • Jeśli aplikacja osadza dane czcionek w dokumencie lub w inny sposób przekazuje dane czcionek do procesu podrzędnego.

Jeśli operacje są wykonywane przy użyciu implementacji, które nie obsługują czcionek zmiennych, te operacje mogą nie generować oczekiwanych wyników. Na przykład pozycje glifów mogą być obliczane dla jednego nazwanego wystąpienia czcionki zmiennej, ale glify mogą być renderowane przy założeniu innego nazwanego wystąpienia. W zależności od implementacji aplikacji wyniki mogą działać w niektórych kontekstach, ale nie w innych kontekstach, w których mogą być używane inne biblioteki. Na przykład tekst może być wyświetlany poprawnie na ekranie, ale nie po wydrukowaniu. Jeśli kompleksowe przepływy pracy są implementowane tylko przy użyciu funkcji DirectWrite, można oczekiwać poprawnego zachowania dla nazwanych wystąpień czcionki zmiennej. 

Ponieważ istniejące interfejsy API DirectWrite obsługują wybór twarzy przy użyciu modelu wagi/rozciągnięcia/stylu, nazwane wystąpienia czcionek używające innych osi odmian będą projektowane na podstawie ogólnego modelu rodziny typograficznej do modelu usług WSS, zgodnie z powyższym opisem. Jest to zależne od czcionki zmiennej, w tym tabeli "atrybutów stylu" ('STAT') z podtabliami osi-wartości, których funkcja DWrite używa do odróżnienia tokenów nazw twarzy, które wyznaczają atrybuty wagi, rozciągnięcia lub stylu z tokenów odnoszących się do innych osi odmiany.  

Jeśli czcionka zmiennej nie zawiera tabeli "STAT", zgodnie z wymaganiami dla czcionek zmiennych według specyfikacji OpenType, funkcja DirectWrite będzie traktować czcionkę jako czcionkę inną niż zmienna zawierająca tylko wystąpienie domyślne.  

Jeśli czcionka zawiera tabelę "STAT", ale nie zawiera odpowiednich podtabli osi-wartości, może to prowadzić do nieoczekiwanych wyników, takich jak wiele twarzy, które mają identyczne nazwy twarzy. Takie czcionki nie są obecnie obsługiwane. 

Specyfikacja OpenType umożliwia reprezentację danych konspektu glyph w jednym z dwóch formatów: przy użyciu tabeli "glyf", która używa formatu konspektu TrueType i podpowiedzi lub przy użyciu tabeli "CFF", która używa reprezentacji Compact Font Format ("CFF"). W czcionki zmiennej z konturami TrueType tabela "glyf" jest nadal używana i jest uzupełniana tabelą "gvar", która dostarcza dane odmiany dla konspektów. Oznacza to, że domyślne wystąpienie czcionki zmiennej z konspektami TrueType używa tylko tradycyjnych tabel OpenType, które będą obsługiwane w starszym oprogramowaniu, które nie obsługuje zmiennych czcionek. Jednak w czcionki zmiennej z konturami CFF tabela "CFF" jest zastępowana przez tabelę "CFF2", która hermetyzuje domyślne dane konspektu i skojarzone dane odmiany w jednej tabeli. Dane CFF są przetwarzane przez oddzielny rasterizator, który jest używany dla danych TrueType, a tabela "CFF2" wymaga zaktualizowanego rasterizatora CFF, który ma obsługę "CFF2". Nie można przetworzyć tabeli "CFF2" przez starsze rasteryzatory CFF. W przypadku czcionki zmiennej z danymi konspektu CFF oznacza to, że nawet wystąpienie domyślne nie będzie działać w starszym oprogramowaniu. 

W aktualizacji systemu Windows 10 Dla twórców funkcja DirectWrite nie obsługuje czcionek zmiennych z danymi konspektu CFF przy użyciu tabeli "CFF2". 

Używanie czcionek zmiennych OpenType

Czcionki zmiennych OpenType mogą być łatwe w użyciu, pamiętając o bieżących ograniczeniach wymienionych powyżej:

  • Obecnie obsługiwane są tylko nazwane wystąpienia czcionki zmiennej.
  • Obecnie obsługiwane są tylko czcionki zmiennych używające danych konspektu TrueType (nie konspektu CFF). 
  • W przypadku czcionek korzystających z osi odmian projektowych innych niż waga, rozciągnięcie lub styl nazwane wystąpienia będą projektowane w modelu rodziny usług WSS, co może spowodować pojawienie się niektórych nazwanych wystąpień jako oddzielnych rodzin (tak jak w przeszłości w przypadku czcionek innych niż zmienne). Aby to obsługiwać, czcionki zmiennych muszą mieć tabelę "STAT", która zawiera odpowiednie podtabela wartości osi.
  • Nazwane wystąpienia czcionek zmiennych są obsługiwane w interfejsach API DirectWrite, ale jeśli niektóre operacje są wykonywane w starszych implementacjach, które nie obsługują czcionek zmiennych, mogą one generować nieprawidłowe wyniki. 
  • Niektóre interfejsy API DirectWrite używają DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH i DWRITE_FONT_STYLE wyliczenia do określania wagi, rozciągnięcia i atrybutów stylu podczas wybierania twarzy. Jeśli czcionka zmiennej używa odpowiednich osi odmian, ale ma wiele nazwanych wystąpień, które wymagają bardziej szczegółowego stopnia szczegółowości, nie wszystkie nazwane wystąpienia będą wybierane w tych interfejsach API.

Czcionki zmiennych OpenType, które są zgodne z tymi wymaganiami, można zainstalować z powłoki systemu Windows tak samo jak inne czcionki OpenType, a także mogą być używane w niestandardowych zestawach czcionek utworzonych przez aplikację.  

Po zainstalowaniu w systemie wszystkie nazwane wystąpienia czcionki zmiennej zostaną uwzględnione w zestawie czcionek zwróconych przez wywołanie metody IDWriteFontFamily3::GetSystemFontSet metody. Należy pamiętać, że zestaw czcionek jest płaską listą bez hierarchii grupowania rodzin, ale każdy element w zestawie ma właściwość nazwa rodziny oparta na modelu rodziny usług WSS. Zestaw czcionek można filtrować dla określonego wystąpienia zmiennej o nazwie przy użyciu IDWriteFontSet::GetMatchingFonts metod. W przypadku używania GetMatchingFonts przeciążenia, które przyjmuje wartość familyName, określona nazwa rodziny musi używać nazwy zgodnej z modelem rodziny czcionek WSS. Pełną listę nazw rodzin zgodnych z usługą WSS występujących w zestawie czcionek można uzyskać przy użyciu IDWriteFontSet::GetPropertyValues metod przy użyciu DWRITE_FONT_PROPERTY_ID_FAMILY_NAME.  

Podobnie wszystkie nazwane wystąpienia czcionki zmiennej będą reprezentowane w kolekcji czcionek zwróconej przez metodę IDWriteFactory::GetSystemFontCollection. Ponieważ elementy kolekcji czcionek to rodziny czcionek oparte na modelu usług WSS, nazwane wystąpienia czcionki zmiennej mogą być reprezentowane w kolekcji jako elementy członkowskie dwóch lub większej liczby rodzin czcionek. Jeśli jest używana metoda IDWriteFontCollection::FindFamilyName, parametr familyName musi być nazwą rodziny zgodną z usługą WSS. Aby znaleźć wszystkie nazwy rodzin zgodne z usługą WSS z kolekcji czcionek, aplikacja może przechodzić w pętli przez każdą rodzinę i wywoływać IDWriteFontFamily::GetFamilyNames, choć może być łatwiej uzyskać odpowiedni zestaw czcionek i użyć metody GetPropertyValues zgodnie z powyższym opisem. 

Podczas pracy z czcionkami niestandardowymi do tworzenia zestawu czcionek można użyć różnych metod opisanych w niestandardowych zestawów czcionek tematu. Aby dodać czcionkę zmiennej do niestandardowego zestawu czcionek, IDWriteFontSetBuilder1::AddFontFile metoda jest zalecana, ponieważ obsługuje czcionki zmiennych i doda wszystkie nazwane wystąpienia czcionki zmiennej w jednym wywołaniu. Obecnie nie ma możliwości dodania pojedynczych nazwanych wystąpień niestandardowej czcionki zmiennej do zestawu czcionek przy użyciu IDWriteFontSetBuilder::AddFontFaceReference metod, ponieważ nie ma możliwości utworzenia odwołania do twarzy czcionki określającej, które z nazwanych wystąpień z pliku czcionki zmiennej ma być zamierzone. Oznacza to, że obecnie nie ma możliwości dodawania nazwanych wystąpień czcionki niestandardowej do niestandardowego zestawu czcionek z przypisanymi właściwościami niestandardowymi. Oznacza to z kolei, że czcionki zmiennych niestandardowych obecnie nie mogą być łatwo używane w połączeniu z interfejsami API DirectWrite dla czcionek zdalnych. Jeśli nazwane wystąpienia czcionki zmiennej są uwzględniane w zestawie czcionek systemowych, jednak odwołania do twarzy czcionek dla każdego nazwanego wystąpienia będą już istnieć i można je dodać do niestandardowych zestawów czcionek, w tym z użyciem niestandardowych wartości właściwości. Aby uzyskać więcej informacji, zobacz temat Custom Font Sets (Niestandardowe zestawy czcionek). 

Podczas pracy z czcionkami zmiennych DWRITE_FONT_WEIGHT DirectWrite i wyliczenia DWRITE_FONT_STRETCH są ściśle połączone z osiami wagi i szerokości zdefiniowanymi w specyfikacji OpenType, ale nie są takie same. Najpierw skala liczbowa dla dowolnej osi odmiany zawsze obsługuje wartości ułamkowe, podczas gdy fontWeight i fontStretch używają liczb całkowitych. Skala osi wagi OpenType używa wartości z zakresu od 1 do 1000, które są również obsługiwane przez czcionkęWeight. W związku z tym zmiana wartości osi wagi odmiany na fontWeight jest stosunkowo niewielka: czcionka Zgłoszona dla nazwanego wystąpienia może być zaokrąglona z dokładnej wartości używanej do definiowania nazwanego wystąpienia w czcionki. Rozróżnienie między funkcją DirectWrite fontStretch a skalą osi szerokości OpenType jest większe: funkcja DirectWrite używa wartości z zakresu od 1 do 9, po usWidthClass wartości tabeli OpenType OS/2, podczas gdy skala osi szerokości OpenType używa wartości dodatnich reprezentujących wartość procentową normalnej szerokości. Dokumentacja usWidthClass w specyfikacji OpenType zawiera mapowanie wartości od 1 do 9 i procent normalnych. Wartość fontStretch zgłoszona dla nazwanego wystąpienia może obejmować zaokrąglanie podczas konwertowania z wartości osi szerokości. 

Podczas tworzenia IDWriteTextFormatnależy określić kolekcję czcionek i właściwości czcionki zgodnej z usługą WSS (nazwa rodziny, waga, rozciągnięcie i styl). Dotyczy to również ustawiania właściwości formatowania czcionek w IDWriteTextLayout zakresie tekstu. Właściwości można uzyskać z obiektu IDWriteFontFace3 lub z IDWriteFont i IDWriteFontFamily obiektów reprezentujących określone nazwane wystąpienie. Jak zaobserwowano powyżej, wartości zwracane przez metody GetWeight i GetStretch mogą być zaokrąglane przybliżenia rzeczywistych wartości osi używanych do zdefiniowania nazwanego wystąpienia, ale Funkcja DirectWrite zamapuje kombinację właściwości z powrotem do żądanego nazwanego wystąpienia. 

Podobnie, jeśli aplikacja używa IDWriteFontFallbackBuilder do tworzenia niestandardowych danych rezerwowych czcionek, rodziny są określane dla mapowań zakresów znaków przy użyciu nazw rodzin zgodnych z usługą WSS. Powrót czcionki w trybie DirectWrite jest oparty na rodzinach z opcją DirectWrite wybierającą wariant w rodzinie rezerwowej, która jest najbliższym dopasowaniem dla wariantu rodziny początkowej. W przypadku wariantów obejmujących wymiary inne niż waga, rozciągnięcie i styl, funkcja DirectWrite obecnie nie będzie mogła wybrać takich wariantów w rodzinie rezerwowej, chyba że niestandardowe dane rezerwowe zostały utworzone specjalnie w celu zapewnienia mapowań rezerwowych dla rodzin, które mają określone atrybuty innych niż WSS, takie jak warianty rozmiaru optycznego "Caption".