Содержание | Предыдущая | Следующая

9. ПРОГРАММИРОВАНИЕ С ПОМОЩЬЮ Турбограф'а

9.1. Создание и использование программ

Запись программ на Турбо Паскале или Турбо Си, воспроизводящих нарисованный вами рисунок, уже рассмотрена выше. Вот те действия, которые нужно выполнить:

  • нарисовать рисунок;
  • воспользоваться пунктом меню Диск/Записать программу...;
  • выбрав нужный язык программирования, выполнить запись.
  • На диск будет записан файл с расширением PAS, C, или EXE.

    Дальнейшее использование EXE-файла здесь не обсуждается. Что же можно делать с полученными программами на Паскале и Си?

    Во-первых, откомпилируйте и выполните их, чтобы убедиться в их работоспособности.

    Текст полученных программ вы можете использовать для включения в свою программу созданных рисунков. Для этого необходимо (В примерах для упрощения изложения взяты рисунок и программы с именем PICTURE):

    ПАСКАЛЬ: Используя операции копирования блока и Clipboard встроенного редактора Турбо Паскаля, перенесите в свою программу 1) описания констант и текст процедуры DrawPICTURE; 2) в том месте вашей программы, где требуется воспроизвести рисунок, поместить вызов процедуры DrawPICTURE.

    Если на рисунке были составные объекты, скопируйте в свою программу и процедуры, которые вызываются из процедуры DrawPicture. Не забудьте также упомянуть в предложении uses вашей программы модуль TgUnit, который служит для поддержки процедур, соответствующих составным объектам.

    СИ: Используя операции копирования блока и Clipboard встроенного редактора Турбо Си, перенесите в свою программу 1)описания инициализированных переменных и текст функции DrawPICTURE(); 2) в том месте вашей программы, где требуется воспроизвести рисунок, поместить вызов функции DrawPICTURE.

    Если вы хотите использовать в своей программе несколько рисунков, полученных с помощью Турбограф'а, то нужно учесть, что Турбограф XXI всегда одинаково обозначает константы: PolyLine1, PolyLine2 и т.д.

    Когда фрагменты полученных с помощью Турбограф'а программ объединяются в одном файле, следует поместить описания констант (инициализированных переменных) внутрь описаний процедур (функций), сделав их локальными.

    Пример.

    ПАСКАЛЬ: В автоматически полученной программе было:

    const
       PolyLine1 : array[1..6] of integer =
           ( 193, 216, 193, 86, 467, 86 );
    var
       grDriver : Integer;
       grMode : Integer;
       ErrCode : Integer;
       Key : Char;

    procedure DrawPICTURE;
    begin
       SetFillStyle( SolidFill, Green );
       Bar( 185, 224, 476, 78 );
       DrawPoly( 3, PolyLine1 );
       SetTextStyle( TriplexFont, HorizDir, 4 );
       OutTextXY( 270, 128, 'Привет' );
    end;

    После преобразования:

    procedure DrawPICTURE;
    const
       PolyLine1 : array[1..6] of integer =
          ( 193, 216, 193, 86, 467, 86 );
    begin
       SetFillStyle( SolidFill, Green );
       Bar( 185, 224, 476, 78 );
       DrawPoly( 3, PolyLine1 );
       SetTextStyle( TriplexFont, HorizDir, 4 );
       OutTextXY( 270, 128, 'Привет' );
    end;

    СИ: В автоматически полученной программе было:

    int PolyLine1[] =
       { 193, 216, 193, 86, 467, 86 };

    void DrawPICTURE()
    {
       setfillstyle( SOLID_FILL, GREEN );
       bar( 185, 224, 476, 78 );
       drawpoly( 3, PolyLine1 );
       settextstyle( TRIPLEX_FONT, HORIZ_DIR, 4 );
       outtextxy( 270, 128, "Привет" );
    }

    После преобразования:

    void DrawPICTURE()
    {
       int PolyLine1[] =
          { 193, 216, 193, 86, 467, 86 };
       setfillstyle( SOLID_FILL, GREEN );
       bar( 185, 224, 476, 78 );
       drawpoly( 3, PolyLine1 );
       settextstyle( TRIPLEX_FONT, HORIZ_DIR, 4 );
       outtextxy( 270, 128, "Привет" );
    }

    Однако будет лучше, если каждый рисунок оформить как отдельный модуль на Паскале или отдельным файлом на Си. Для этого нужно:

    ПАСКАЛЬ: 1) Слово program заменить на unit; 2) Вычеркнуть упоминание Crt из предложения uses; 3) Удалить раздел переменных; 4) Удалить все операторы главной программы между begin и end. 5) Записать слово implementation перед строчкой uses; 6) Записать слово interface перед строчкой implementation; 7) Скопировать заголовок процедуры DrawPICTURE и поместить копию в следующей строчке после слова interface

    Пример.

    До преобразования:

    program PICTURE;
    { Программа получена с помощью графической системы }
    { Турбограф XXI 2.1 Copyright (c) 1993,98 С.Свердлов }

    uses
       Graph, Crt;

    const
       PolyLine1 : array[1..6] of integer =
          ( 193, 216, 193, 86, 467, 86 );
    var
       grDriver : Integer;
       grMode : Integer;
       ErrCode : Integer;
       Key : Char;


    procedure DrawPICTURE;
    begin
       SetFillStyle( SolidFill, Green );
       Bar( 185, 224, 476, 78 );
       DrawPoly( 3, PolyLine1 );
       SetTextStyle( TriplexFont, HorizDir, 4 );
       OutTextXY( 270, 128, 'Привет' );
    end;

    begin
       grDriver := Detect;
       InitGraph( grDriver, grMode, '' );
       ErrCode := GraphResult;
       if ErrCode = grOk then begin
          DrawPICTURE;
          Key := ReadKey;
          CloseGraph;
          end
       else
          WriteLn('Ошибка графики: ', GraphErrorMsg(ErrCode));
    end.

    После преобразования:

    unit PICTURE;

    interface

    procedure DrawPICTURE;

    implementation

    uses
       Graph;

    const
       PolyLine1 : array[1..6] of integer =
          ( 193, 216, 193, 86, 467, 86 );

    procedure DrawPICTURE;
    begin
       SetFillStyle( SolidFill, Green );
       Bar( 185, 224, 476, 78 );
       DrawPoly( 3, PolyLine1 );
       SetTextStyle( TriplexFont, HorizDir, 4 );
       OutTextXY( 270, 128, 'Привет' );
    end;

    begin
    end.

    Теперь в своей программе для использования рисунка нужно написать:

    uses
       ..., PICTURE;

    ...

    DrawPICTURE;

    ...

    СИ: 1) Убрать все директивы кроме #include <graphics.h>; 2) удалить функцию main(); 3) поместить описание переменных внутрь функции DrawPicture()

    Пример.

    До преобразования:

    /* PICTURE */
    /* Программа получена с помощью графической системы */
    /* Турбограф XXI 2.0 Copyright (c) 1993,XXI С.Свердлов */

    #include <stdlib.h>
    #include <stdio.h>
    #include <conio.h>
    #include <graphics.h>

    int PolyLine1[] =
       { 193, 216, 193, 86, 467, 86 };

    void DrawPICTURE()
    {
       setfillstyle( SOLID_FILL, GREEN );
       bar( 185, 224, 476, 78 );
       drawpoly( 3, PolyLine1 );
       settextstyle( TRIPLEX_FONT, HORIZ_DIR, 4 );
       outtextxy( 270, 128, "Привет" );
    }

    void main()
    {
    int grDriver = DETECT, grMode, ErrorCode;
       initgraph(&grDriver, &grMode, "");
       ErrorCode = graphresult();
       if (ErrorCode == grOk) {
          DrawPICTURE();
          getch();
          closegraph();
          }
       else
          printf("Ошибка графики: %s\n", grapherrormsg(ErrorCode));
    }

    После преобразования

    /* PICTURE */

    #include <graphics.h>

    void DrawPICTURE()
    {
       int PolyLine1[] =
          { 193, 216, 193, 86, 467, 86 };
       setfillstyle( SOLID_FILL, GREEN );
       bar( 185, 224, 476, 78 );
       drawpoly( 3, PolyLine1 );
       settextstyle( TRIPLEX_FONT, HORIZ_DIR, 4 );
       outtextxy( 270, 128, "Привет" );
    }

    Описанное здесь преобразование законченной программы в независимую единицу компиляции (модуль) поможет избежать проблем для рисунков большого объема. При этом программирующие на Си должны еще побеспокоиться об использовании дальних ссылок (меню Настройка/Си-программа).

    При записи программ для сложных рисунков большого размера может случиться так, что компиляция такой программы будет невозможна по причине слишком большой длины исходного текста. В этом случае может помочь возможность записи данных в виде отдельного файла (модуля). Эта возможность предусмотрена в меню Настройка/Паскаль-программа, Настройка/Си-программа.

    9.2. Особенности программной реализации составных объектов

    Если на рисунке вы создали составные объекты, в записанной программе появятся процедуры (здесь и далее пояснения даются применительно к программе на Паскале. Для языка Си все аналогично), по одной на каждый вид составного объекта. Каждой копии составного объекта на рисунке будет соответствовать в программе вызов соответствующей процедуры. Кроме того, в предложении использования программы будет упомянут модуль TgUnit, содержащий средства, обеспечивающие преобразования составных объектов.

    Программный модуль TgUnit

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

    Копии составного объекта отличаются только местоположением на экране. В этом случае процедура будет иметь такой заголовок (для примера взято название Proc1):
    procedure Proc1( x, y : integer );
    Этой разновидности процедур соответствует тип DrawMProcType, определенный в интерфейсной секции модуля TgUnit. При рассмотрении других вариантов ограничимся ссылками на соответствующие типы процедур из TgUnit.

    Копии отличаются положением и есть хотя бы одна копия, отличающаяся от оригинала цветом — будет записана процедура типа
    DrawMCProcType = procedure (x, y, Color, FillColor : integer);

    Есть копия, отличающаяся узором или толщиной линии, стилем закраски, но ни одна копия не отличается от оригинала по размеру — тип процедуры:
    DrawMCAProcType = procedure (x, y, Color, FillColor,
       FillStyle : integer;
       FillPattern : FillPatternType;
       LineStyle : integer;
       LinePattern : word;
       LineWidth : integer );

    Копии отличаются только местоположением и размерами —
    DrawProcType = procedure ( x1, y1, x2, y2 : integer );

    При отличиях в размерах среди копий есть хотя бы одна, отличающаяся цветом — тип процедуры:
    DrawCProcType = procedure ( x1, y1, x2, y2,
       Color, FillColor : integer );

    Есть копии, отличающиеся размерами, типом, толщиной линий или узором закраски:
    DrawCAProcType = procedure ( x1, y1, x2, y2,
       Color, FillColor : integer;
       FillStyle : integer;
       FillPattern : FillPatternType;
       LineStyle : integer;
       LinePattern : word;
       LineWidth : integer );

    Одни составные объекты, могут быть частью других, значит одни процедуры будут в программе вызывать другие. При этом в трансформациях, происходящих с составных объектом, должны участвовать и составляющие его объекты. Это относится как к изменению положения и размеров, так и к изменению атрибутов.

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

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

    procedure ProcBegin; — сохраняет в специально для этих целей организуемом стеке текущие установки графической системы с целью их последующего восстановления (с помощью Return) по завершении работы процедуры составного объекта.

    Если в полученной вами программе процедуры составных объектов содержат из числа процедур TgUnit только обращения к ProcBegin и Return, вы можете удалить строки с этими вызовами. При этом вы избавитесь от необходимости использовать в своей программе TgUnit, ускорив ее работу и уменьшив объем. Процедура же, из которой удалены обращения к ProcBegin и Return, не будет восстанавливать текущие установки по завершении своей работы.

    procedure DrawBegin( Width, Height, x1, y1, x2, y2 : integer ); — выполняет те же действия, что и процедура ProcBegin, а также записывает в стек данные, необходимые для масштабирования каждого графического элемента того составного объекта, который она рисует.

    procedure StoreXY( x, y : integer ); — сохраняет в стеке данные, необходимые для масштабирования ломаных и многоугольников.

    procedure StoreColors( Color, FillColor : integer ); — сохраняет в стеке цвета.

    procedure StoreAttr( ... ); — сохраняет в стеке атрибуты линий и закраски.

    procedure Return; — извлекает из стека и восстанавливает текущие установки графической системы.

    function tgX( x : integer ) : integer; — Вычисляет новую координату X точки с учетом масштабирования. Параметры масштабирования берутся из стека.

    function tgY( y : integer ) : integer; — Вычисляет координату Y точки с учетом масштабирования.

    procedure Draw( Proc : DrawProcType; x1, y1, x2, y2 : integer ); — рисует составной объект, определяемый процедурой Proc, в составе другого составного объекта, когда последний подвергался масштабированию.

    procedure DrawM( Proc : DrawMProcType; x, y : integer ); — то же, что и Draw, но для процедур типа DrawMProcType.

    procedure DrawC( Proc : DrawCProcType; x1, y1, x2, y2, Color, FillColor : integer ); — то же, что и Draw, но для процедур типа DrawCProcType (с учетом цвета).

    procedure DrawMC( Proc : DrawMCProcType; x, y, Color, FillColor : integer ); — то же, что и DrawC, но для процедур типа DrawMCProcType.

    procedure DrawCA( Proc : DrawCAProcType;
       x1, y1, x2, y2 : integer;
       Color, FillColor : integer;
       FillStyle : integer;
       FillPattern : FillPatternType;
       LineStyle : integer;
       LinePattern : word;
       LineWidth : integer ); — то же, что и Draw, но для процедур типа DrawCAProcType (с учетом цветов и атрибутов).

    procedure DrawMCA( Proc : DrawMCAProcType;
       x, y : integer;
       Color, FillColor : integer;
       FillStyle : integer;
       FillPattern : FillPatternType;
       LineStyle : integer;
       LinePattern : word;
       LineWidth : integer ); — то же, что и DrawCA, но для процедур типа DrawMCAProcType.

    Кроме уже упомянутых, в модуле TgUnit определены процедуры, названия которых получены из названий процедур стандартного модуля Graph добавлением префикса tg (tgPutPixel, tgLine и т.д.). Все эти процедуры выполняют те же действия, что и соответствующие им процедуры модуля Graph, но с учетом переноса, масштабирования, замены цветов и атрибутов. При этом фактические параметры при вызове этих процедур определяют положение, цвет и атрибуты соответствующего графического элемента в составном объекте-оригинале. Данные для масштабирования и замены цветов при воспроизведении копии объекта эти процедуры берут из стека.

    9.3. Компоновка графического драйвера и шрифтов с программой

    Графическая библиотека BGI фирмы Борланд допускает компоновку с программой (присоединение к EXE-файлу) графического драйвера и файлов штриховых шрифтов. Это дает ряд преимуществ: во-первых, для работы программы требуется только EXE-файл (если присоединены и драйвер и шрифты); во-вторых, при переключении шрифтов они не будут всякий раз загружаться с диска, что, возможно, несколько ускорит работу; в-третьих, программа не будет зависеть от модификаций шрифта (русифицирован, украинизирован, искажен), а будет всегда использовать шрифт, предусмотренный разработчиком. Есть и недостатки - несколько присоединенных к программе шрифтов постоянно занимают оперативную память, кроме того, происходит дублирование шрифтов и драйверов и на диске (в составе EXE-файлов).

    Рассмотрим, каким образом выполняется компоновка. Впрочем, основную разъяснительную работу выполнит Турбограф XXI, которому вы можете заказать формирование программы на Паскале и Си, предусматривающее присоединение драйверов и шрифтов. (Меню Настройка/Паскаль-программа, Настройка/Си-программа). В тексте программ будут все необходимые команды и директивы, требующиеся для правильной компоновки, с которыми вы и можете ознакомиться. (Компоновка драйвера и шрифтов к EXE-программе, создаваемой Турбограф'ом, происходит автоматически и не требует какого-либо Вашего участия).

    Для выполнения компоновки файлы драйверов (расширение .BGI) и шрифтов (расширение .CHR) должны быть преобразованы в стандартный формат объектных модулей (расширение .OBJ). Для этого необходимо:

    ПАСКАЛЬ: Запустить программу BINOBJ.EXE, имеющуюся в комплекте Турбо Паскаля и предназначенную для преобразования произвольного двоичного файла в стандартный формат объектного модуля. В качестве параметров следует указать 1) преобразуемый файл; 2) имя получаемого объектного файла; 3) внешнее имя объектного модуля.

    Пример:

    BINOBJ egavga.bgi egavga EgaVgaDriverProc

    Следует пояснить смысл и название третьего параметра. Дело в том, что полученный объектный модуль присоединяется к программе "под видом" процедуры, название которой и выступает в роли третьего параметра. Это название не обязано быть таким, как в приведенном примере. В нем выбрано имя, используемое Борланд в примерах, иллюстрирующих компоновку, и в модуле BGIDriv. При выполнении компоновки встроенный редактор связей Турбо Паскаля по соответствию внешних имен устанавливает необходимые связи отдельных частей программы.

    Компоновка драйвера и шрифтов под видом процедур, а не констант, кажущаяся на первый взгляд довольно странной, позволяет более разумно использовать память. Известно, что суммарный объем глобальных переменных и типизированных констант в программе на Турбо Паскале ограничен 64 килобайтами и отнимать от этой величины внушительные объемы драйверов и шрифтов не следует.

    Чтобы вам не пришлось записывать громоздкие команды вызова BINOBJ, в комплекте Турбограф'а имеется командный файл PAS_OBJ.BAT, в котором предусмотрены вызовы BINOBJ.EXE для преобразования всех драйверов и шрифтов.

    При компоновке драйверов и шрифтов удобно пользоваться модулями BGIDriv и BGIFons, исходный текст которых имеется в комплекте Турбо Паскаля версии 6.0 и 7.0 (В предшествующих версиях эти модули называются Drivers и Fonts). Турбограф XXI предусматривает это, а также позволяет формировать модуль TGFonts, подобный BGIFonts и включающий компоновку шрифтов, не входящих в комплект Турбо Паскаля.

    Объединение компонуемых шрифтов и драйверов в отдельные модули позволяет избежать ограничения в 64 килобайта на размер кода каждого программного модуля.

    СИ: Запустить программу BGIOBJ.EXE, имеющуюся в комплекте Турбо Си (Си++) и предназначенную для преобразования файлов графических драйверов и шрифтов в стандартный формат объектного модуля. В качестве параметров следует указать для драйверов и шрифтов, входящих в комплект компилятора — имя (без расширения) преобразуемого файла; для прочих шрифтов и драйверов — 1) название преобразуемого файла; 2) имя получаемого объектного файла; 3) внешнее имя объектного модуля.

    Примеры:

    BGIOBJ egavga

    BGIOBJ syse.chr syse _syse_font

    Для получения объектного модуля с дальними ссылками используется ключ /f:

    BGIOBJ /f egavga

    BGIOBJ /f syse.chr sysef  syse_font_far

    Чтобы вам не пришлось записывать громоздкие команды вызова BGIOBJ, в комплекте Турбограф'а имеются командные файлы C_OBJ.BAT и CFAR_OBJ.BAT, в которых предусмотрены вызовы BGIOBJ.EXE для получения объектных модулей с ближними и дальними ссылками для всех драйверов и шрифтов.

    Полученные объектные файлы драйвера и шрифтов следует упомянуть в файле проекта.

    Использование драйвера VESA16.BGI

    Графический драйвер VESA16.BGI, обслуживающий 16-цветные режимы видеоадаптера SVGA, может работать только с новой версией графической BGI-библиотеки (модуль Graph), поставляемой в составе Борланд Паскаль 7.0 и Борланд Си. Его особенность состоит в том, что он может работать как в реальном, так и в защищенном режиме. Поэтому, если вы используете, например, Турбо Паскаль 6.0, то не сможете в своих программах использовать VESA16.BGI и получить доступ к 16-цветным режимам SVGA. Наоборот, старые версии стандартных драйверов и драйверы VESA256.BGI и VGA256.BGI не будут работать в программах защищенного режима.

    9.4. Файлы рисунков программы Турбограф XXI

    В этом разделе приводится исчерпывающая информация о структуре файлов рисунка программы Турбограф XXI (формат TGP).

    Структура файла рисунка (.TGP)

    Файл рисунка программы Турбограф XXI (TGP-файл) состоит из заголовка и последовательности элементов рисунка. Последовательность элементов файла повторяет последовательность операторов создаваемой Турбограф'ом программы на Турбо Паскале и Турбо Си. Заканчивается файл рисунка признаком "Конец рисунка" — два нулевых байта.

    Заголовок и конец рисунка могут рассматриваться как элементы.

    Заголовок имеет длину 128 байт и располагается в начале файла. Турбограф XXI способен обрабатывать и файлы без заголовков, но в этом случае некоторые возможности будут утрачены. Структура заголовка такова:

    Смещение поля

    Длина поля

    Тип поля

    Содержание поля

    0

    2

    char

    Содержит 'TG'

    2

    1

    byte

    Длина названия версии

    3

    11

    char

    Название версии ('2.0')

    14

    2

    word

    Код граф. драйвера

    16

    2

    word

    Код граф. режима

    18

    2

    integer

    Минимальная координата по Х

    20

    2

    integer

    Минимальная координата по Y

    22

    2

    integer

    Максимальная координата по Х

    24

    2

    integer

    Максимальная координата по Y

    26

    4

    longint

    Размер объектов

    30

    9

    string[8]

    Название графического драйвера

    39

    89

      Зарезервировано

    Каждый элемент файла рисунка состоит из идентифицирующего целочисленного кода и параметров. Набор элементов соответствует составу графической библиотеки фирмы Борланд. Значения кодов выбраны так, что соответствуют номеру процедуры или функции (при нумерации с шагом 10) в интерфейсной секции модуля Graph (Турбо Паскаль 6.0). Некоторые элементы, не имеющие полных аналогов в библиотеке Борланд, имеют коды, превосходящие 1000.

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

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

    Копии составных объектов, имеющиеся среди этих элементов ссылаются на соответствующие им описания с помощью смещения, задаваемого, как один из параметров.

    Ниже описывается структура каждого элемента, из которых состоит файл рисунка. При знакомстве с описаниями следует иметь в виду, что, если не оговорено иное, все параметры имеют целый тип (integer) и занимают в файле 2 байта. Код элемента также целого типа (2 байта). Параметры каждого элемента записываются в файле непосредственно за кодом. Элементы записываются в файл друг за другом.

    Обозначения:

    x, y, x1, y1, x2, y2 — координаты;

    R, Rx, Ry — радиусы;

    C — цвет;

    N — число точек.

    Порядок следования параметров в описании строго соответствует порядку их записи в файл.

    Название

    Код

    Параметры

    Примечание

    1

    Заголовок файла

    18260

    описаны выше  

    2

    Точка (PutPixel)

    290

    x, y, C  

    3

    Отрезок (Line)

    360

    x1, y1, x2, y2  

    4

    Ломаная (DrawPoly)

    420

    N, x1, y1, x2, y2, ..., xN, yN  

    5

    Многоугольник (FillPoly)

    430

    N, x1, y1, x2, y2, ..., xN, yN  

    6

    Многоточие

    1010

    C, N, x1, y1, x2, y2, ..., xN, yN  

    7

    Установить цвет (SetColor)

    590

    C  

    8

    Прямоугольная рамка (Rectangle)

    390

    x1, y1, x2, y2  

    9

    Установить стиль закраски (SetFillStyle)

    460

    FS, C FS - номер стиля закраски

    10

    Закрашенный прямоугольник (Bar)

    400

    x1, y1, x2, y2  

    11

    Окружность (Circle)

    510

    x, y, R  

    12

    Дуга эллипса (Ellipse)

    520

    x, y, SA, EA, Rx, Ry SA, EA -- начальный и конечный углы дуги

    13

    Закрашенный эллипс (FillEllipse)

    530

    x, y, Rx, Ry;  

    14

    Заливка (FloodFill)

    480

    x, y, C C - цвет границы

    15

    Текст (OutTextXY)

    740

    x, y, S S - строка текста в форме с указанием длины в первом байте. Занимает L+1 байт, где L-число символов

    16

    Установить стиль текста (SetTextStyle)

    760

    F, D, S F - номер шрифта; D - направление; S - размер;

    17

    Установить пользовательский размер символов (SetUserCharSize)

    770

    Mx, Dx, My, Dy Mx/Dx - масштабные коэффициенты для направления вдоль текста; My/Dy - масштабные коэффициенты для направления поперек текста

    18

    Установить тип линии (SetLineStyle)

    380

    NS, P, T NS - номер стиля; P - шаблон; T - толщина

    19

    Установить пользовательский стиль текста

    1020

    Name, D, S Name - название файла шрифта - строка из 4 символов, занимает 5 байт; D - направление; S - размер; Реализуется вызовом SetTextStyle (InstallUserFont (Name), D, S);

    20

    Установить выравнивание текста (SetTextJustify)

    750

    H, V H - способ выравнивания по горизонтали; V - способ выравнивания по вертикали;

    21

    Эллиптический сектор (Sector)

    570

    x, y, SA, EA, Rx, Ry SA, EA - начальный и конечный углы сектора;

    22

    Дуга окружности (Arc)

    490

    x, y, SA, EA, R SA, EA - начальный и конечный углы дуги;

    23

    Круговой сектор (PieSlice)

    560

    x, y, SA, EA, R SA, EA - начальный и конечный углы сектора;

    24

    Установить узор закраски (SetFillPattern)

    470

    FP, C FP - узор закраски (8 байт);

    25

    Установить все цвета в палитре (SetAllPalette)

    620

    Palette : PaletteType Тип PaletteType определен в модуле Graph

    26

    Установить цвет в палитре (SetPalette)

    630

    CN, CV CN - номер цвета (0..15); CV - значение цвета (0..63)

    27

    Установить цвет в RGB-палитре

    680

    С, R, G, B C-цвет; R,G,B - красная, зеленая и синяя составляющие (0..63)

    28

    Начало описания составного объекта (ProcBegin)

    2000

    w, h : integer; Name w, h - ширина и высота; Name - название — строка текста в форме с указанием длины в первом байте. Занимает L+1 байт, где L-число символов

    29

    Конец описания составного объекта

    2010

    нет  

    30

    Копия составного объекта (вызов процедуры составного объекта)

    2020

    x1, y1, x2, y2; Attr : AttrType; Offset : longint Attr — атрибуты копии составного объекта; OffSet — смещение начала описания составного объекта относительно точки вызова

    31

    Старт (безусловный переход)

    2030

    Offset : longint Offset — смещение первого объекта, следующего за описаниями составных объектов, относительно текущей точки

    32

    Конец рисунка.

    0

    Параметров нет Помещается в конце файла рисунка.

    Модуль TGP

    Рассмотренная выше структура файла рисунка определена в программном модуле TGP.PAS, который является частью программы Турбограф XXI.

    В интерфейсной секции этого модуля определены:

    Константы, задающие коды элементов файла рисунка (префикс TGP);

    Константы, определяющие длину в байтах каждого элемента (Для элементов переменной длины задается длина постоянной части) (суффикс Len);

    Типы, определяющие заголовок и структуру каждого элемента (tHeader и TGPItemType).

    В части, относящейся к заголовку, модуль TGP являет собой небольшое упражнение по объектно-ориентированному программированию (ООП) и условной компиляции. Появилось оно оттого, что в Турбограф'е объекты используются, но в выставляемом напоказ модуле мне не хотелось злоупотреблять модными ООП-штучками. Перед вами — результат компромисса — два варианта: с объектами и без. Сравнивайте.

    9.5. Использование модуля TGPlay

    В модуле TGP определена лишь структура файла рисунка, средства же воспроизведения (рисования, исполнения, интерпретации, проигрывания) рисунков содержатся в модуле TGPLAY.PAS.

    Вот его интерфейсная секция:

    unit TgPlay;

    interface

    uses
       TGP;

    const
       playOk = 0;
       playIllegalCode = -99;

    procedure Play( var V );
    procedure Show( var V; Width, Height, x1, y1, x2, y2 : integer );
    function PlayError : integer;
    function PlayErrorMsg( ErrCode : integer ) : string;

    Основной здесь является процедура Play - исполнитель (проигрыватель, интерпретатор) рисунков.

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

    Процедура Play может воспроизводить рисунки размером более 64К. Перед вызовом должен быть включен графический режим.

    Процедура Show (показать) является расширением Play, обеспечивая возможность воспроизведения рисунка с масштабированием. Ее дополнительные параметры означают следующее:

    Width, Height — исходные ширина и высота рисунка (могут быть взяты, например, из заголовка TGP-файла);

    x1, y1, x2, y2 — координаты углов прямоугольника, в котором рисунок должен быть показан.

    Использование процедуры Show иллюстрирует пример из файла SHOWFILE.PAS (см. ниже).

    Функция PlayError возвращает код результата рисования, выполненного последним вызовом Play или Show. Значение PlayError=playOk=0 означает, что рисование выполнено без ошибок.

    PlayError возвращает единственный код "собственной" ошибки — значение PlayError = playIllegalCode означает, что в образе файла рисунка встретился недопустимый код элемента. Остальные возможные значения заимствуются PlayError у функции GraphResult (стандартный модуль Graph).

    PlayError (в отличие от GraphResult) сохраняет свое значение при повторных обращениях.

    Функция PlayErrorMsg позволяет по коду, возвращаемому PlayError, получить текстовое сообщение на русском языке.

    Воспроизведение файлов рисунка

    В комплекте Турбограф'а есть программа FILEPLAY.PAS, иллюстрирующая возможность использования модуля TGPlay на примере воспроизведения рисунка PICTURE.TGP, расположенного в текущем каталоге диска. Файл вначале считывается в динамически выделенный буфер памяти, а затем рисуется вызовом процедуры Play. Вот текст этого примера:

    program FilePlay;
    {
    Эта программа иллюстрирует использование модуля TGPlay,
    входящего в состав графического редактора ТурбографXXI 2.1.
    Воспроизводится рисунок из файла PICTURE.TGP. Размер
    файла не должен превышать 65520 байт. Наличие файла на
    диске и ошибки чтения диска не контролируются.
    Необходимы модули TGPlay и TGP.
    }

    uses
       Graph, Crt, TGPlay;

    var
       PicFile : file;
       PicPtr : Pointer;
       grDriver : integer;
       grMode : integer;
       ErrCode : integer;
       Key : char;

    begin
       { Чтение файла рисунка в память }
          Assign( PicFile, 'PICTURE.TGP');
          Reset( PicFile, 1);
          GetMem( PicPtr, FileSize( PicFile ) );
          BlockRead( PicFile, PicPtr^, FileSize( PicFile ) );

       { Инициализация графики и рисование }
          grDriver := Detect;
          InitGraph( grDriver, grMode, '' );
          ErrCode := GraphResult; 
          if ErrCode = grOk then begin
             { Рисование }
             Play( PicPtr^ );
             if PlayError <> PlayOk then begin
                CloseGraph;
                WriteLn( PlayErrorMsg(PlayError));
             end;
             Key := ReadKey;
             CloseGraph;
             end
          else
             WriteLn('Ошибка графики: ', GraphErrorMsg(ErrCode));
    end.

    Воспроизведение с масштабированием

    При воспроизведении рисунка возможно его масштабирование, если вместо процедуры Play использовать процедуру Show из модуля TgPlay. Иллюстрацией этому служит следующий пример из файла SHOWFILE.PAS:

    program ShowFile;
    {
    Эта программа иллюстрирует использование модуля TGPlay,
    входящего в состав графического редактора ТУРБОГРАФ XXI.
    Демонстрируется возможность показа рисунка в измененном
    масштабе. Рисунок показывается дважды уменьшенным в задан-
    ное число раз. Уменьшение задается константой Shrink.
    Воспроизводится рисунок из файла PICTURE.TGP. Размер
    файла не должен превышать 65520 байт. Наличие файла на
    диске и ошибки чтения диска не контролируются.
    Необходимы модули TGPlay, TgUnit и TGP.
    }

    uses
       Graph, Crt, TGPlay, TgUnit, TGP;

    const
       Shrink = 2;

    var
       PicFile : file;
       PicPtr : Pointer;
       grDriver : integer;
       grMode : integer;
       ErrCode : integer;
       Key : char;
       Width : integer;
       Height : integer;
       x1, y1 : integer;
       x2, y2 : integer;

    begin
       { Чтение файла рисунка в память }
          Assign( PicFile, 'PICTURE.TGP');
          Reset( PicFile, 1);
          GetMem( PicPtr, FileSize( PicFile ) );
          BlockRead( PicFile, PicPtr^, FileSize( PicFile ) );

       { Инициализация графики и рисование }
          grDriver := Detect;
          InitGraph( grDriver, grMode, '' );
          ErrCode := GraphResult;
          if ErrCode = grOk then begin
             { Рисование }
             Width := GetMaxX;
             Height := GetMaxY;
             x1 := 0;
             y1 := 0;
             x2 := GetMaxX div Shrink;
             y2 := GetMaxY div Shrink;
             Show( PicPtr^, Width, Height, x1, y1, x2, y2 );
             if Shrink > 1 then
                Show( PicPtr^, Width, Height,
                      x2, y2, x2+x2-x1, y2+y2-y1);
             if PlayError <> PlayOk then begin
                CloseGraph;
                WriteLn( PlayErrorMsg(PlayError));
             end;
             Key := ReadKey;
             CloseGraph;
             end
          else
             WriteLn('Ошибка графики: ', GraphErrorMsg(ErrCode));
    end.

    Компоновка файлов рисунка с программой

    Подобно тому, как с программой компонуются драйверы и шрифты, к ней можно присоединить файлы рисунка и воспроизводить их, пользуясь процедурами Play и Show. По сравнению с включением на уровне исходного текста это позволит сэкономить память для рисунков большого объема. Время рисования практически не изменится. Чтобы дополнительно сэкономить 128 байт можно перед компоновкой удалить из файла рисунка заголовок.

    Пример компоновки рисунка PICTURE.TGP с программой содержится в файле LINKPLAY.PAS:

    program LinkPlay;
    {
    Воспроизводится рисунок из файла PICTURE.OBJ, присоеди-
    неный к программе под видом процедуры PicProc.
    Для получения объектного файла PICTURE.OBJ используйте
    программу BINOBJ.EXE из комплекта Турбо Паскаля:
    BINOBJ picture.tgp picture picproc
    Необходимы модули TGPlay и TGP.
    }

    uses
       Graph, Crt, TGPlay;

    var
       grDriver : integer;
       grMode : integer;
       ErrCode : integer;
       Key : char;

    procedure PicProc; external;
    {$L PICTURE.OBJ}

    begin
       grDriver := Detect;
       InitGraph( grDriver, grMode, '' );
       ErrCode := GraphResult;
       if ErrCode = grOk then begin
          Play( @PicProc^ );
          if PlayError <> PlayOk then begin
             CloseGraph;
             WriteLn( PlayErrorMsg(PlayError) );
          end;
          Key := ReadKey;
          CloseGraph;
          end
       else
          WriteLn('Ошибка графики: ', GraphErrorMsg(ErrCode) );
    end.

    9.6. Преобразование программы на Паскале в файл рисунка

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

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

    Когда вы располагаете исчерпывающими данными о строении файла рисунка, сделать это не так уж трудно. Однако еще проще эти проблемы решаются с помощью модуля TGraph. Программирующие на Паскале могут получить файл, содержащий рисунок, созданный вашей программой, добавив в эту программу одну букву или слово!

    Получение рисунков с помощью TGraph

    Модуль TGraph (файл TGRAPH.PAS) служит заменой стандартному модулю Graph, хотя сам использует его. Все обращения из вашей программы к процедурам и функциям модуля Graph подменяются обращениями к одноименным процедурам TGraph, которые кроме воспроизведения графических элементов обеспечивают и запись соответствующих данных в файл рисунка.

    Простейший вариант использования TGraph для получения файла рисунка состоит в том, что в тексте имеющейся программы упоминание модуля Graph в предложении uses заменяется на TGraph, т.е. добавляется одна буква. Вот пример программы, которая выводит на экран 100 случайных отрезков нечаянного цвета и одновременно создает файл #TGRAPH#.TGP (такое название дается файлу по умолчанию):

    program RandLine;

    uses
       TGraph;

    const
       n = 100;

    var
       grDriver : integer;
       grMode : integer;
       ErrCode : integer;
       i : integer;

    begin
       grDriver := Detect;
       InitGraph( grDriver, grMode, '' );
       ErrCode := GraphResult;
       if ErrCode = grOk then begin
          for i := 1 to n do begin
             SetColor( Random( GetMaxColor + 1 ) );
             Line( Random(GetMaxX), Random(GetMaxY),
                   Random(GetMaxX), Random(GetMaxY) );
          end;
          ReadLn;
          CloseGraph;
          end
       else
          WriteLn('Ошибка графики: ', GraphErrorMsg(ErrCode));
    end.

    Вы видите, что единственное отличие этой программы от программы, которая просто рисует, состоит в том, что вместо "Graph" написано "TGraph".

    Интерфейсная секция модуля TGraph почти повторяет интерфейсную секцию Graph. Отличий два. Первое — отсутствуют описания типов. Второе — добавлены средства управления формированием файла рисунка.

    Если в вашей программе используются определенные в модуле Graph типы, то они по-прежнему должны заимствоваться из Graph. То есть в общем случае

    ДЛЯ ЗАПИСИ ФАЙЛА РИСУНКА НУЖНО ДОБАВИТЬ В ПРЕДЛОЖЕНИЕ USES ВАШЕЙ ПРОГРАММЫ (МОДУЛЯ) ПОСЛЕ УПОМИНАНИЯ GRAPH — TGRAPH.

    Пример.

    Было: uses Graph, Crt;

    Стало: uses Graph, TGraph, Crt;

    ("TGraph" вписывается обязательно ПОСЛЕ "Graph"!)

    В модуле TGraph имеются следующие процедуры и функции для управления выводом файла рисунка:

    procedure SetTGPName( Name : string ); — Установить имя файла для записи рисунка. Может вызываться до первого вызова процедур и функций, выполняющих рисование. Если Name не содержит расширения, то устанавливается расширение .TGP. Если SetTGPName не используется, то файл рисунка получает имя #TGRAPH#.TGP.

    procedure OffTGP; — Выключить запись в файл рисунка (по умолчанию запись включена). Позволяет в ходе выполнения прикладной программы временно отключить запись в файл рисунка выводимых на экран элементов.

    procedure OnTGP; — Снова включить запись в файл рисунка. Используется при необходимости после OffTGP.

    function TGPOn : Boolean; — Проверить включена ли запись в файл рисунка.

    Вот фрагмент демонстрационной программы Борланд BGIDEMO.PAS, в которую включены вызовы процедур, регулирующих вывод в файл TGP:

    { Turbo Graphics }
    { Copyright (c) 1985, 1990 by Borland International, Inc. }
    program BGIDemo;
    (*
    Turbo Pascal 6.0 Borland Graphics Interface(BGI)demonstration
    program. This program shows how to use many features of
    the Graph unit.

    NOTE: to have this demo use the IBM8514 driver, specify a
    conditional define constant "Use8514" (using the {$DEFINE}
    directive or Options\Compiler\Conditional defines) and then
    re-compile.
    *)

    uses
       Crt, Dos, Graph, TGraph; { Добавлено "TGraph" ! }

    ......

    begin { program body }
       SetTGPName('BGIDEMO');
       OffTGP; { Выключаем }
       Initialize;
       ReportStatus;
       AspectRatioPlay;
       FillEllipsePlay;
       OnTGP; { Включаем для записи секторов }
       SectorPlay;
       OffTGP; { Снова выключаем ... }

    ......

       CloseGraph;
    end.

     Содержание | Предыдущая | Следующая


    Турбограф XXI (Версия 2.1)
    Copyright © 1998 С.Свердлов
    Замечания и предложения: tg@mail.ru