C dla każdego (cz. 8.)

Czcionki

Tym razem omówimy podstawy posługiwania się różnymi rodzajami kroju pisma.

Czym jest wynalazek Gutenberga, tłumaczyć nie trzeba. W wypadku Amigi czcionki należałoby podzielić ze względu na pochodzenie, czyli pamięć stałą bądź masową. Do chwili obecnej w ROM-ie znajduje się tylko jedna rodzina fontów, o nazwie "topaz". Pozostałe czcionki umieszcza się zazwyczaj w katalogu "FONTS:". Podstawowoą informacją o czcionce jest jej wielkość.
Przyjęto, że podaje się wysokość w punktach oraz atrybuty, takie jak pogrubienie, pochylenie, zwane kursywą, oraz podkreślenie.

W dawnych czasach wszystkie czcionki Amigi były zapisane w postaci plików, opisujących punkt po punkcie daną literę. Plików było tyle, ile dostępnych rozmiarów danej czcionki. Pliki te umieszcza się w podkatalogu o nazwie takiej, jak nazwa kroju. Oprócz tego istnieją też pliki z rozszerzeniem "font", które zawierają pełne informacje o kroju (dostępne wielkości itp). Tego typu czcionki nazywane są bitmapowymi, ich niewątpliwą zaletą jest to, że szybko się je otwiera. Obecnie możliwe jest również zastosowanie czcionek wektorowych. W ich wypadku zapisane są jedynie kontury liter, na których podstawie generuje się poszczególne wielkości. Taka organizacja pozwala zmieniać wielkość i proporcje bez utraty jakości, jednak wymaga czasochłonnych obliczeń (ale możliwe jest stworzenie i zapisanie czcionek bitmapowych na podstawie wektorowych danych). System 2.0 pozwala skalować zarówno czcionki wektorowe, jak i bitmapowe, jednak jakość tych ostatnich pozostawia nieco do życzenia.

Obsługą czcionek zajmuje się biblioteka graficzna oraz "diskfont.library", która jest odpowiedzialna za czcionki dyskowe. Czcionki otwiera się za pomocą funkcji:

struct TextFont *OpenFont(struct TextAttr *textAttr); - z "graphics.library"
struct TextFont *OpenDiskFont(struct TextAttr *textAttr); - z "diskfont.library"

Funkcje te udostępniają nam czcionkę. Pierwsza może otworzyć jedynie czcionki znajdujące się już w pamięci, druga natomiast doskonale radzi sobie zarówno z czcionkami znajdującymi się na dysku, jak i w pamięci. Argumentem tych funkcji jest struktura opisująca: "TextAttr" lub "TTextAttr" - druga pojawiła się w OS 2.04 i jest rozszerzona o pole "tta_Tags" będące wskaźnikiem na tablicę struktur "TagItem".

struct TextAttr
{
STRPTR tta_Name;
UWORD ttaYsize;
UBYTE ttaStyle;
UBYTE ttaFlags;
struct TagItem *ttaTags;
};

Aby poinformować system, że używamy rozszerzonej struktury, należy ustawić w polu "ttaStyle" flagę "FSF_TAGGED". Wspomniane pole zawiera również opis stylu czcionki, którą chcemy otworzyć:

FS_NORMAL - brak udziwnień,
FSF_BOLD - pogrubienie,
FSF_ITALIC - kursywa,
FSF_UNDERLINE - podkreślenie.

Pole "tta_Name" zawiera pełną nazwę czcionki (z przyrostkiem "font"). Wysokość czcionki jest zapisana w polu "tta_Size", w polu zaś "tta_Flags" umieszcza się następujące flagi:

FPF_ROMFONT - czcionka z ROM-U (topaz 8 lub 9).
FPF_DISKFONT - czcionka z dysku.
FPF_DESIGNED - ustawienie tej flagi powoduje, że zostaje zablokowana możliwość generowania brakujących rozmiarów. Używa się jej. gdy nie chcemy, aby biblioteka Disk Font "wydumała" brakujący rozmiar czcionki bitmapowej, jako że rezultaty bywają niezbyt piękne.

Starsza wersja struktury ma cztery pierwsze pola, różnica polega również na braku pierwszego "t" w nazwie pól.

W wypadku nowej struktury w polu "tta_Flags" umieszczamy wskaźnik na tablice "tagów", w której można umieścić tag "TA_DeviceDPI".
Za jego pomocą zmienia się stosunek szerokości do wysokości czcionki. Dzięki zastosowaniu "TA_DeviceDPI" można panować nad szerokością czcionek o jednakowej wysokości.

Po przydługawym omówieniu parametrów przejdźmy do rezultatów funkcji - obie zwracają wskaźnik na strukturę "TextFont" (patrz "graphics/text.h). Pola "tf_YSize", "tf_XSize" tej struktury zawierają wymiary czcionki, przy czym "tf_XSize" jest uśrednione w wypadku czcionek proporcjonalnych, to znaczy takich w których litery mają różną szerokość ("W" jest szersze niż "i"). Aby odróżnić czcionki proporcjonalne od tych o stałej szerokości (ang. fixed width), należy zbadać czy w polu "tf_Flags" otrzymanej struktury jest ustawiena flaga "FPF_PROPORTIONAL". Kolejną przydatną informacją jest pole "tf_Baseline", które zawiera wysokość w punktach od szczytu czcionki do linii bazowej, czyli miejsca, poza które wystają w dół jedynie ogonki z liter takich jak: 'j', 'y', jak również naszych narodowych "ogonkowców". Przykład w poprzednim odcinku drukował napisy na nieco dziwnej wysokości - zarówno powyżej, jak i poniżej kursora graficznego. Na wysokości kursora położona była właśnie linia bazowa.

Po otwarciu czcionki otrzymujemy wskaźnik na strukturę "TextFont". Aby zacząć pisać, należy tę strukturę "podłączyć" do RastPortu za pomocą funkcji biblioteki graficznej:

void SetFont(struct RastPort *rp, struct TextFont *textFont);

Argumentami są wskaźniki na RastPort i strukturę "TextFont". Po przydzieleniu czcionki do RastPortu możemy korzystać z niej za pomocą funkcji Text(). Uaktualniane są również pola RastPortu, opisujące czcionkę: "TxFlags", "TxWidth", "TxHeight", "TxBaseline" oraz "AlgoStyle" (o tym wkrótce). Nie musimy się przejmować przywracaniem poprzedniej czcionki ani wartości pól RastPortu przed zamknięciem okna - system nie zwraca na nie najmniejszej uwagi.

A skoro jesteśmy już przy zamykaniu, to po zakończeniu współpracy z czcionką należy poinformować o tym system za pomocą funkcji pochodzącej z biblioteki graficznej:

void CloseFont(struct TextFont *textFont);

Jedynym jej argumentem jest wskaźnik na czcionkę, czyli to, co zwróciła funkcja OpenFont() lub OpenDiskFont().

Przepraszamy Czytelników za ciągłe opóźnienia oraz dzielenie na części w sposób często niezbyt elegancki i niezgodny z treścią artykułów. Jest to spowodowane naszym "gadulstwem", które zmusiło redakcję do podzielenia niektórych części. Przykro nam, że przykład zobaczycie dopiero za miesiąc, jdenak przdstawione dziś infromacje powinny wystarczyć do pierwszych samodzielnych eksperymentów.