Kreslení oblouků a kružnic
Ke kreslení oblouků, kružnic a elips se v Cairo používá ta samá funkce: Cairo::Context::arc(). Tato funkce má pět argumentů. První dva jsou souřadnice středu oblouku, třetí je poloměr oblouku a konečně poslední dva argumenty definují počáteční a koncový úhel oblouku. Všechny úhly se určují v radiánech, takže nakreslení kružnice je to stejné, jako nakreslení oblouku od 0 do 2 * M_PI radiánů. Úhel 0 leží na kladné ose X (v uživatelském prostoru). Úhel M_PI/2 radiánů (90 stupňů) je v kladném směru osy Y (v uživatelském prostoru). Úhel se zvyšuje ve směru z kladné osy X ke kladné ose Y. Takže s výchozí transformační maticí se úhel zvyšuje po směru hodinových ručiček. (Vzpomeňte, že kladná osa Y jde směrem dolů.)
To draw an ellipse, you can scale the current transformation matrix by different amounts in the X and Y directions. For example, to draw an ellipse with center at x, y and size width, height:
context->save(); context->translate(x, y); context->scale(width / 2.0, height / 2.0); context->arc(0.0, 0.0, 1.0, 0.0, 2 * M_PI); context->restore();
- 16.4.1. Příklad
16.4.1. Příklad
Zde je příklad jednoduchého programu, který kreslí do kreslicí oblasti oblouk, kružnici a elipsu.
File: myarea.h (For use with gtkmm 4)
#ifndef GTKMM_EXAMPLE_MYAREA_H #define GTKMM_EXAMPLE_MYAREA_H #include <gtkmm/drawingarea.h> class MyArea : public Gtk::DrawingArea { public: MyArea(); virtual ~MyArea(); protected: void on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height); }; #endif // GTKMM_EXAMPLE_MYAREA_H
File: main.cc (For use with gtkmm 4)
#include "myarea.h" #include <gtkmm/application.h> #include <gtkmm/window.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(); protected: MyArea m_area; }; ExampleWindow::ExampleWindow() { set_title("DrawingArea"); set_child(m_area); } int main(int argc, char** argv) { auto app = Gtk::Application::create("org.gtkmm.example"); return app->make_window_and_run<ExampleWindow>(argc, argv); }
File: myarea.cc (For use with gtkmm 4)
#include "myarea.h" #include <cairomm/context.h> #include <cmath> MyArea::MyArea() { set_draw_func(sigc::mem_fun(*this, &MyArea::on_draw)); } MyArea::~MyArea() { } void MyArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height) { const int lesser = std::min(width, height); // coordinates for the center of the window const int xc = width / 2; const int yc = height / 2; cr->set_line_width(lesser * 0.02); // outline thickness changes // with window size // first draw a simple unclosed arc cr->save(); cr->arc(width / 3.0, height / 4.0, lesser / 4.0, -(M_PI / 5.0), M_PI); cr->close_path(); // line back to start point cr->set_source_rgb(0.0, 0.8, 0.0); cr->fill_preserve(); cr->restore(); // back to opaque black cr->stroke(); // outline it // now draw a circle cr->save(); cr->arc(xc, yc, lesser / 4.0, 0.0, 2.0 * M_PI); // full circle cr->set_source_rgba(0.0, 0.0, 0.8, 0.6); // partially translucent cr->fill_preserve(); cr->restore(); // back to opaque black cr->stroke(); // and finally an ellipse double ex, ey, ew, eh; // center of ellipse ex = xc; ey = 3.0 * height / 4.0; // ellipse dimensions ew = 3.0 * width / 4.0; eh = height / 3.0; cr->save(); cr->translate(ex, ey); // make (ex, ey) == (0, 0) cr->scale(ew / 2.0, eh / 2.0); // for width: ew / 2.0 == 1.0 // for height: eh / 2.0 == 1.0 cr->arc(0.0, 0.0, 1.0, 0.0, 2 * M_PI); // 'circle' centered at (0, 0) // with 'radius' of 1.0 cr->set_source_rgba(0.8, 0.0, 0.0, 0.7); cr->fill_preserve(); cr->restore(); // back to opaque black cr->stroke(); }
Je tu pár věcí, které v tomto příkladu stojí za zmínku. Ještě jednou, jediný skutečný rozdíl mezi tímto příkladem a předchozím je ve funkci on_draw(), takže se zaměříme jen na ni. Navíc, první část této funkce je hodně podobná předchozímu příkladu, takže ji přeskočíme.
Všimněte si, že v tomto případě jsme téměř vše vyjádřili v pojmech výšky a šířky okna, včetně tloušťky čar. Díky tomu vše při změně velikosti okna správně změní měřítko. Navíc si všimněte, že jsou ve funkci tři samostatné celky kreslení, které jsou obalené v páru funkcí save() a restore(), takže po každém kreslení se vrátíme zpět do známého stavu.
V části kreslící oblouk můžete potkat novou funkci close_path(). Tato funkce se projevuje nakreslením rovné čáry z aktuálního do prvního bodu cesty. Je ale podstatný rozdíl mezi zavoláním close_path() a ručním nakreslením čáry zpět k počátečnímu bodu. Když použijete close_path(), budou čáry spolu pěkně spojené. Když místo toho použijete line_to(), budou čáry sice končit ve stejném bodě, ale Cairo je nijak speciálně nespojí.
Funkce Cairo::Context::arc_negative() je úplně stejná, jako Cairo::Context::arc(), jen úhly se počítají v opačném směru.