Фигуры изображаются одна поверх другой, подобно листам бумаги, в порядке их добавления на экран. По этой причине объект
path
оказался на самом “дне”, просто потому, что он был связан с окном до объекта
rita
. Изображения могут кодироваться во множестве форматов. Здесь мы используем только два из них: JPEG и GIF.
struct Suffix {
enum Encoding { none, jpg, gif };
};
В
нашей библиотеке графического интерфейса изображение в памяти представляется как объект класса
Image
.
struct Image:Shape {
Image(Point xy, string file_name,
Suffix::Encoding e = Suffix::none);
~Image { delete p; }
void draw_lines const;
void set_mask(Point xy, int ww, int hh)
{ w=ww; h=hh; cx=xy.x; cy=xy.y; }
private:
int w,h; // определяем "маскировочное окно" внутри изображения
// по отношению к позиции (cx,cy)
int cx,cy;
Fl_Image* p;
Text fn;
};
Конструктор класса
Image
пытается открыть файл с указанным именем, затем создать рисунок, используя кодировку, указанную в дополнительном аргументе или (как правило) в расширении файла. Если изображение невозможно вывести на экран (например, потому, что файл не найден), класс
Image
выводит на экран объект
Bad_image
. Определение класса
Bad_image
выглядит так:
struct Bad_image:Fl_Image {
Bad_image(int h, int w):Fl_Image(h,w,0) { }
void draw(int x,int y, int, int, int, int) { draw_empty(x,y);
}
};
Работа с изображениями в графической библиотеке довольно сложна, но основная сложность класса
Image
кроется в файле, который обрабатывает его конструктор.
Расширение файла используется для того, чтобы определить вид объекта, создаваемого для хранения изображения ( Fl_JPEG_Image или Fl_GIF_Image). Этот объект создается с помощью оператора
new
и связывается с указателем. Подробности его реализации (в главе 17 рассматривается оператор new и указатели) связаны с организацией библиотеки FLTK и не имеют для нас большого значения.
Теперь настало время реализовать функцию
can_open
, проверяющую, можно ли открыть файл для чтения.
bool can_open(const string& s)
// проверка, существует ли файл s и можно ли его открыть
// для чтения
{
ifstream ff(s.c_str);
return ff;
}
Открыть файл, а затем закрыть его, — довольно примитивный способ проверки, позволяющий отделить ошибки, связанные с невозможностью открыть файл, от ошибок, обусловленных неприемлемым форматированием данных.
Если хотите, можете посмотреть на определение функции
get_encoding
: она просто анализирует суффикс и ищет соответствие в таблице заранее заданных суффиксов. Эта таблица реализована с помощью стандартного типа
map
(подробнее об этом — в разделе 21.6).
Задание
1. Создайте объект класса
Simple_window
размером 800x1000 пикселей.
2. Разместите сетку размером 8?8 пикселей в левой части окна размером 800 на 800 пикселей (так что каждый квадрат сетки имеет размер 100x100 пикселей).
3. Создайте восемь красных квадратов, расположенных по диагонали, начиная с левого верхнего угла (используйте класс
Rectangle
).
4. Подберите изображение размером 200x200 пикселей (в формате JPEG или GIF) и разместите три его копии поверх сетки (каждое изображение покроет четыре квадрата). Если вы не найдете изображения, размеры которого точно равнялись бы 200 пикселям, то, используя функцию
set_mask
, вырежьте соответствующий фрагмент более крупного изображения. Не закрывайте красные квадраты.