Knihovna ClanLib (19)

20. 9. 2004
Doba čtení: 6 minut

Sdílet

Minule jsme si udělali úvod do práce s fonty, dnes naše znalosti rozšíříme. Zabývat se budeme zejména třídou CL_Font.

CL_Font

Už minule jsme si řekli, že CL_Font je třída reprezentující font v ClanLibu. Víme již také, jak zkonstruovat objekt této třídy z parametrů zapsaných v RDF. Podívejme se tedy na to, co s takovýmto objektem můžeme dělat:

int draw(
        int x,
        int y,
        const std::string &str,
        CL_GraphicContext *context = 0) const;

int draw(
        CL_Rect dest,
        const std::string &str,
        CL_GraphicContext *context = 0) const;

int draw(
        int x,
        int y,
        std::string::const_iterator start,
        std::string::const_iterator end,
        CL_GraphicContext *context = 0) const;

int draw(
        CL_Rect dest,
        std::string::const_iterator start,
        std::string::const_iterator end,
        CL_GraphicContext *context = 0) const;

Jak je vidět, především nám CL_Font umožňuje vypsat zadaný řetězec. K tomu slouží metoda draw() v několika přetížených verzích.

Této metodě předáváme vždy údaje o tom, kam se má vykreslovat. Buď tedy zadáme pouze souřadnice x, y, nebo zadáme parametr dest typu CL_Rect. Připomínám, že třída CL_Rect reprezentuje obdelník, tj. obsahuje atributy left, top, right a bottom, tedy souřadnice levého horního a pravého dolního rohu (jelikož obsahuje spoustu užitečných funkcí, zmíním se o ní příště podrobně). Pokud zadáme obdelník, bude se třída CL_Font snažit při vykreslování text zarovnat tak, aby nepřesáhl okraje tohoto obdélníku. Toto zarovnání (word-wrapping) je závislé na tom, jaké znaky považuje CL_Font za oddělovače slov (dají se nastavit metodou set_delims() viz níže).

I vypisovaný řetězec můžeme zadat dvěma způsoby. První možností je předání std::stringu samotného, druhou je předání dvojice iterátorů ohraničujících část řetězce obvyklým způsobem (tj. první znak a jeden znak za).

Parametr context říká, jaký grafický kontext se má použít pro vykreslování, přičemž implicitní nula představuje aktuální kontext CL_Display, a tento parametr tedy obvykle nebudeme zadávat.

void set_delims(const std::string &delims);
std::string get_delims() const;

Pomocí set_delims() můžeme nastavit řetězec znaků, které budou brány za oddělovače slov, což je důležité při případném zarovnávání. Implicitně je takovým oddělovačem znak nové řádky, takže ten nemá smysl zadávat.

Pokud nás zajímá, které znaky jsou považovány za oddělovač slov kromě znaku nové řádky, můžeme použít metodu get_delims(), která vrátí řetězec těchto znaků.

int get_width_offset() const;
int get_height_offset() const;

void set_width_offset(int offset);
void set_height_offset(int offset);

Jestliže nás zajímají hodnoty width_offset či height_offset (význam popsán v minulém dílu), můžete je zjistit pomocí prvních dvou uvedených metod, případně je můžete pomocí druhých dvou metod nastavit.

void set_color(float r, float g, float b, float a = 1.0f);
void set_color(const CL_Color& c);

void get_color(float &red, float &green, float &blue, float &alpha) const;
CL_Color get_color() const; 

Metody set_color() nám umožňují změnit barevnost vykreslovaného obrázku. Pomocí get_color() zjistíme, jak je tato barevnost nastavena. Barevnost zadáváme buď jako RGBA, nebo jako CL_Color (třída reprezentující barvu).

float get_alpha() const;
void set_alpha(float alpha);

Pomocí těchto dvou metod můžeme nastavit průhlednost fontu (0.0f je úplná průhlednost a 1.0f je nulová průhlednost).

void set_scale(float x, float y);
void get_scale(float &x, float &y) const;

Pomocí set_scale() můžeme upravit měřítko vykreslování ve vodorovném i svislém směru. Zadáme-li za x a y 1.0f, vykreslí se příště font ve své skutečné velikosti. Zadáme-li však například 0.5f za x i y, bude jeho velikost poloviční, naopak 2.0f znamená dvojnásobné zvětšení v daném směru (tj. můžeme písmo třeba pouze zúžit zadáním x=0.8f, y=1.0f).

Je samozřejmé, že velké zvětšování nebude vypadat zrovna pěkně na rozdíl od zmenšování, kde ke ztrátám kvality víceméně nedochází. Uložíte-li si tedy obrázky znaků v maximální velikosti, kterou budete potřebovat, vystačíte si s jednou verzí, jelikož pro menší verzi tohoto písma použijete zmenšování. Uvážíte-li navíc možnosti jistých změn barevnosti a průhlednosti, zjistíte, že z jedné bitmapy s obrázky jednotlivých písmenek se toho dá vyzískat opravdu mnoho.

int get_height() const;

int get_height(
        const std::string &str,
        CL_Size max_size = CL_Size(0,0)) const;

int get_height(
        std::string::const_iterator start,
        std::string::const_iterator end,
        CL_Size max_size = CL_Size(0,0)) const;

První verze metody get_height(), tj. ta bez parametrů, vrací výšku nejvyššího znaku v pixelech.

Dalším dvěma verzím předáváme řetězec jako string či dva iterátory a dostaneme odpověď, jakou výšku v pixelech bude mít tento text vypsaný pomocí draw(). Zadáme-li i poslední parametr max_size typu CL_Size (třída reprezentující rozměry obdelníku), dostaneme výšku vypsaného textu ořezaného do obdelníku těchto rozměrů.

int get_width(unsigned int letter) const;

int get_width(
        const std::string &str,
        CL_Size max_size = CL_Size(0,0)) const;

int get_width(
        std::string::const_iterator start,
        std::string::const_iterator end,
        CL_Size max_size = CL_Size(0,0)) const;

Pomocí get_width() jsme schopni zjistit šířku konkrétního znaku nebo šířku celého řetězce s uvážením případného ořezávání obdobně jako u get_height().

CL_Size get_size(unsigned int letter) const;

CL_Size get_size(
        const std::string &str,
        CL_Size max_size = CL_Size(0,0)) const;

CL_Size get_size(
        std::string::const_iterator start,
        std::string::const_iterator end,
        CL_Size max_size = CL_Size(0,0)) const;

Pokud chceme zjistit šířku i výšku najednou, můžeme použít příslušné verze metody get_size() a nemusíme postupně volat get_height() a get_width().

CL_Rect bounding_rect(int x, int y, const std::string &str) const;

CL_Rect bounding_rect(CL_Rect dest, const std::string &str) const;

CL_Rect bounding_rect(
        int x, int y,
        std::string::const_iterator start,
        std::string::const_iterator end) const;

CL_Rect bounding_rect(
        CL_Rect dest,
        std::string::const_iterator start,
        std::string::const_iterator end) const; 

Metoda bounding_rect() je obdobou get_size(), vrací však nejen rozměry, ale i pozici, tj. celý CL_Rect (obdélník opsaný textu vypsanému na zadanou pozici). Tato metoda samozřejmě nepřináší oproti get_size() žádnou novou informaci, jelikož souřadnice musíme zadat nejprve sami. Každopádně pokud potřebujeme CL_Rect a ne CL_Size, budeme za ni rádi.

bool is_glyph(unsigned int chr) const;

Pomocí is_glyph() si můžeme ověřit, zda pro zadaný znak máme obrázek.

bitcoin_skoleni

Ke třídě CL_Font bych ještě dodal, že má copy konstruktor a implicitní konverzi na bool umožňující zjistit, zda se jedná o platný objekt. Vnitřně je implementován pomocí CL_LazyCopyPtr.

Závěrem

Časem snad ještě přijde řada na některé speciality CL_Fontu, které jsem dosud zatajil. Každopádně pro práci s fonty již máme k dispozici poměrně dost silné nástroje. Příště si proto dovolím udělat odbočku k třídám jako CL_Rect nebo CL_Size. Plánuji se také časem zase trochu vrátit k tvorbě GUI, a to zejména k CL_Menu.

Autor článku