Смекни!
smekni.com

Программирование в СИ (стр. 6 из 8)

Последний аргумент charsize управляет масштабом выводимых символов. Диапазон допустимых значений: от 1 до 10 для всех графических шрифтов и дополнительное значение 0 только для векторных. Положительное значение charsize указывает на одинаковое увеличение символов по обеим осям. Если для векторных шрифтов задать charsize, равный USER_CHAR_SIZE (определена как 0), то при этом определяются два независимых коэффициента масштабирования – для ширины и высоты символа. По умолчанию в этом режиме знакогенератор рисует символы векторного шрифта в базовом варианте в соответствии с описанием из chr-файла. Однако есть возможность изменить масштаб с помощью функции

void far setusercharsize(int mult_x,int div_x,int mult_y,int div_y);

Данная функция устанавливает новые размеры символа, умножая ширину и высоту базового варианта каждого символа на значения выражения ((double)mult_x / div_x) и ((double)mult_y / div_y) соответственно.

Главным недостатком автоматической инициализации знакогенератора при помощи функции settextstyle является то, что она обращается к диску для чтения chr-файла во время выполнения программы. Альтернативой автоматической инициализации знакогенератора является статическое включение в программу таблицы символов векторных шрифтов. Для этого сначала нужно при помощи утилиты bgiobj.exe превратить chr-файлы в объектные файлы c расширением .obj. Затем их можно включить в программу как обычные объектные файлы.

Перед статической инициализацией знакогенератора необходима регистрация нужной таблицы векторных шрифтов, для чего предусмотрена функция, которой нужно передать местоположение в оперативной памяти таблицы символов шрифта:

int registerbgifont(void (*font)(void));

В качестве указателей используются имена, уже определенные в объектных файлах шрифтов. Ниже приведены описания тех имен, которые нужно употреблять для шрифтов из минимального набора:

void triplex_font(void);void small_font(void);void sansserif_font(void);void gothic_font(void);

При успешной регистрации шрифта возвращаемое значение неотрицательно. Далее для инициализации знакогенератора используется функция settextstyle с необходимыми установками для шрифта. Тогда в присутствии на диске chr-файла отпадает всякая необходимость.

Графическая система позволяет позиционировать на странице видеопамяти выводимый текст с точностью до пикселя, для этого функциям вывода текста нужно некоторую опорную точку. Расположением выводимой строки относительно опорной точки управляет функция

void far settextjustify(int horiz,int vert);

Ее аргументы могут принимать значения констант перечислимого типа text_just:

enum text_just{LEFT_TEXT=0, CENTER_TEXT, RIGHT_TEXT,BOTTOM_TEXT, TOP_TEXT};

В случае ошибки функция settextjustify устанавливает код ошибки, равный -11, и сохраняет предыдущий режим позиционирования.

Позиционирование горизонтальных строк происходит следующим образом. Если представить прямоугольник, в который вписана выводимая строка, то пара аргументов horiz и vert описывают положение опорной точки в прямоугольнике.

При инициализации графического режима опорная точка всех строк располагается в левом верхнем углу прямоугольника, в который вписывается горизонтальная строка.

В позиционировании вертикальных строк имеются некоторые особенности. Нужно помнить, что функция settextjustify управляет размещением относительно опорной точки именно прямоугольника, содержащего текст. Из этого следует, что по отношению к самому тексту (поскольку он повернут на 90 градусов) позиционирование справа и слева от опорной точки определяется аргументом vert, а сверху или снизу – аргументом horiz. Аргумент vert обрабатывается так же, как и для горизонтальной строки. Аргумент horiz ведет себя по-другому. При значениях LEFT_TEXT и RIGHT_TEXT он дает одинаковый результат – текстовый прямоугольник располагается слева от опорной точки.

В графической библиотеке существует функция, позволяющая получить информацию о текущем режиме вывода графических текстовых сообщений:

void far gettextsettings(struct textsettingstype far *texttypeinfo);

Информация заносится в область памяти, выделенную в программе и содержащую следующую структуру:

struct textsettingstype{int font,direction,charsize;int horiz,vert;};

Для правильного размещения текста на странице необходимо знать размеры занимаемого им пространства, которое зависит от типа шрифта и его масштабирования. Эту информацию выдают функции:

int far textheight(char far *text_string); int far textwidth(char far *text_string);

Они возвращают высоту и ширину (в пикселях) прямоугольника, в который был бы вписан текст при выводе строки text_string знакогенератором текущего шрифта с учетом установленного в данный момент масштаба шрифта. Сам вывод текста при этом не производится.

При своей работе функции вывода текста создают в видеопамяти рисунок символов строки, используя таблицу выбранного шрифта. Код, который при этом заносится в атрибуты пикселей, есть текущее значение рисующего цвета (номер входа во внутреннюю палитру), устанавливаемое функцией setcolor. Никаких битовых операций с атрибутами пикселей видеопамяти не предусмотрено. Линии, которыми рисуются символы векторных шрифтов, всегда сплошные тонкие, они не могут модифицироваться функцией setlinestyle.

В отличие от текстового режима, фон выводимых символов (цвет прямоугольника, в который вписана строка) не изменяется. Если нужно вывести строку на каком-либо фоне, то фон нужно нарисовать отдельно, например с помощью функции bar. Другим важным отличием графического режима от текстового является отсутствие режима мигания символа. Можно имитировать процесс мигания, управляя внутренней палитрой с помощью функции setpalette.

Функций вывода текста две:

void far outtext(char far *text_string);void far outtextxy(int x,int y,char far *text_string);

Обе в качестве аргумента получают указатель на выводимую строку символов. Отличие между этими функциями состоит в выборе опорной точки при позиционировании сообщения на странице. Функция outtext использует для этого текущую графическую позицию. Функция outtextxy получает координаты опорной точки через аргументы x и y. Координаты задаются в системе координат текущего графического окна. При установке режима отсечения изображения за пределами окна обе функции также обеспечивают отсечение фрагментов текста, выходящего за пределы графического окна.


2. ПРИЕМЫ ПРОГРАММИРОВАНИЯ ГРАФИЧЕСКОГО РЕЖИМА

2.1. Подключение графической библиотеки

Для подключения графической библиотеки можно использовать один из двух приемов. Во-первых, включитьвменюоболочкиBC++3.1 опцию Options-Linker-Libraries-Graphics library. Во-вторых, создать проект и включить в него исходные cpp-файлы и библиотеку LIB\graphics.lib.

Графический режим может не работать в оболочке, если не хватает места в динамической памяти. Следует увеличить ее размер в пункте Options-Debugger-Heapsize.

2.2. Инициализация графического режима

Простейшую инициализацию осуществляет следующий код

#include<graphics.h>

void main()

{

int gd = DETECT, gm;

initgraph( &gd, &gm, “c:&bsol;bc31&bsol;bgi” );

// работаем в графическом режиме

putpixel(100, 200, WHITE);

// ……….

If(!getch())

getch();

closegraph();

}


2.3. Включение драйвера и шрифтов в исполняемый файл

Для включения графического драйвер egavga.bgiв исполняемый файл необходимо:

а) в командной строке выполнить

C:&bsol;BC31&bsol;BGI&bsol;bgiobj.exeegavga

и получить файл egavga.obj;

б) создать проект в оболочке с помощью команды меню Project-Open и включить в него файл egavga.obj и исходные cpp-файлы;

в) затем в тексте программы записать код

registerbgidriver(EGAVGA_driver);

initgraph(&gd, &gm, “”);

Для включения графических шрифтов (файлов с расширением chr) в исполняемый файл необходимо:

а) в командной строке выполнить

C:&bsol;BC31&bsol;BGI&bsol;bgiobj.exe goth

и получить файл goth.obj;

б) создать проект в оболочке с помощью команды меню Project-Open и включить в него файл goth.obj и исходные cpp-файлы;

в) затем в тексте программы записать код

registerbgifont(GOTHIC_font);

initgraph(&gd, &gm, “c:&bsol;borlandc&bsol;bgi”);

//…………………

settextstyle(GOTHIC_FONT, HORIZ_DIR, 10);

outtext(“Hello”);

//…………………


2.4. Рисование геометрических фигур

а) Нарисуем красное солнце

setcolor(RED);

circle(100, 100, 50); //краснаяокружность

setfillstyle(SOLID_FILL, RED);

floodfill(100, 100, RED); /* рисуем красный круг, указывая внутреннюю точку области и цвет контура */

б) Нарисуем в центре экрана квадрат со стороной a, повернутый относительно центра Cна угол j против часовой стрелки. Пусть С(x0, y0) – математические координаты точки. Тогда вершины неповернутого квадрата имеют координаты

(x0 + (sqrt(2) / 2) · a · cos( p/4 + p/2 · k),

y0 + (sqrt(2) / 2) · a · sin( p/4 + p/2 · k)), где k = 0, 1, 2, 3.

При повороте на угол j получаем математические вершины

(fk, gk) = (x0 + (sqrt(2) / 2) · a · cos( p/4 + p/2 · k + j),

y0 + (sqrt(2) / 2) · a · sin( p/4 + p/2 · k + j)),

где k= 0, 1, 2, 3.

В соответствии с данными, приведенными п.2.11, переводим математические координаты (fk, gk) в координаты пикселей (uk, vk). Затем определяем целочисленный массив Aкоординат вершин замкнутого многоуольника

{u[0], v[0], u[1], v[1] , u[2], v[2], u[3], v[3], u[0], v[0] }.


Теперь рисуем квадрат с помощью одной функции

drawpoly(5, A);

2.5. Выделение памяти под большие одномерные массивы

Элементами массивов могут быть структуры большого размера. Если и размер массива значителен, то выделить динамическую память под такой массив одним вызовом функции malloc нельзя. Прототип этой функции

void *malloc( unsigntd int T);

Поэтому максимальный размер блока памяти, который она выделяет, не превосходит 64К.

Предлагается эмулировать одномерный динамический массив двумерным динамическим массивом с использованием массива
указателей.

Например, выделим память под longT=50000l структур

struct comp {

float re, im;

};

Общий размер такого массива равен 50 000 * 8 = 400 000 байт. Выберем размеры двумерного массива

intm = 1000; // количество столбцов выбираем произвольно

intn = (int)((T– 1)/ m) +1; // количество строк, нумерация строк
с нуля