English 中文 Español Deutsch 日本語 Português
Графика в библиотеке DoEasy (Часть 79): Класс объекта "Кадр анимации" и его объекты-наследники

Графика в библиотеке DoEasy (Часть 79): Класс объекта "Кадр анимации" и его объекты-наследники

MetaTrader 5Примеры | 15 июля 2021, 12:39
3 042 0
Artyom Trishkin
Artyom Trishkin

Содержание


Концепция

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

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

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

Таким образом, сегодня мы немного переработаем созданные в предыдущих статьях классы рисования, разработаем класс базового объекта-кадра анимации и разработаем два класса его наследников — класс кадра текстовой анимации и класс прямоугольного кадра анимации. Создадим класс для хранения списков этих объектов-кадров и дадим возможность работы с ними из объекта-формы.


Доработка классов библиотеки

Для начала доработаем ранее созданные классы библиотеки. В файл \MQL5\Include\DoEasy\Defines.mqh впишем список типов кадров анимации и список типов рисуемых фигур в классе прямоугольного кадра анимации:

//+------------------------------------------------------------------+
//| Данные для работы с анимацией графических элементов              |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Список  типов кадров анимации                                    |
//+------------------------------------------------------------------+
enum ENUM_ANIMATION_FRAME_TYPE
  {
   ANIMATION_FRAME_TYPE_TEXT,                         // Текстовый кадр анимации
   ANIMATION_FRAME_TYPE_QUAD,                         // Прямоугольный кадр анимации
  };
//+------------------------------------------------------------------+
//| Список типов рисуемых фигур                                      |
//+------------------------------------------------------------------+
enum ENUM_FIGURE_TYPE
  {
   FIGURE_TYPE_PIXEL,                                 // Точка
   FIGURE_TYPE_PIXEL_AA,                              // Точка со сглаживанием AntiAlliasing
   
   FIGURE_TYPE_LINE_VERTICAL,                         // Вертикальная линия
   FIGURE_TYPE_LINE_VERTICAL_THICK,                   // Вертикальный отрезок произвольной линии заданной толщины с использованием алгоритма сглаживания
   
   FIGURE_TYPE_LINE_HORIZONTAL,                       // Горизонтальная линия
   FIGURE_TYPE_LINE_HORIZONTAL_THICK,                 // Горизонтальный отрезок произвольной линии заданной толщины с использованием алгоритма сглаживания
   
   FIGURE_TYPE_LINE,                                  // Произвольная линия
   FIGURE_TYPE_LINE_AA,                               // Линия со сглаживанием AntiAlliasing
   FIGURE_TYPE_LINE_WU,                               // Линия со сглаживанием WU
   FIGURE_TYPE_LINE_THICK,                            // Отрезок произвольной линии заданной толщины с использованием алгоритма сглаживания
   
   FIGURE_TYPE_POLYLINE,                              // Ломаная линия
   FIGURE_TYPE_POLYLINE_AA,                           // Ломаная линия со сглаживанием AntiAlliasing
   FIGURE_TYPE_POLYLINE_WU,                           // Ломаная линия со сглаживанием WU
   FIGURE_TYPE_POLYLINE_SMOOTH,                       // Ломаная линия заданной толщины с использованием двух алгоритмов сглаживания
   FIGURE_TYPE_POLYLINE_THICK,                        // Ломаная линия заданной толщины с использованием алгоритма сглаживания    
   
   FIGURE_TYPE_POLYGON,                               // Многоугольник
   FIGURE_TYPE_POLYGON_FILL,                          // Закрашенный многоугольник
   FIGURE_TYPE_POLYGON_AA,                            // Многоугольник со сглаживанием AntiAlliasing
   FIGURE_TYPE_POLYGON_WU,                            // Многоугольник со сглаживанием WU
   FIGURE_TYPE_POLYGON_SMOOTH,                        // Многоугольник заданной толщины с использованием двух алгоритмов сглаживания
   FIGURE_TYPE_POLYGON_THICK,                         // Многоугольник заданной толщины с использованием алгоритма сглаживания
   
   FIGURE_TYPE_RECTANGLE,                             // Прямоугольник
   FIGURE_TYPE_RECTANGLE_FILL,                        // Закрашенный прямоугольник
   
   FIGURE_TYPE_CIRCLE,                                // Окружность
   FIGURE_TYPE_CIRCLE_FILL,                           // Закрашенный круг
   FIGURE_TYPE_CIRCLE_AA,                             // Окружность со сглаживанием AntiAlliasing
   FIGURE_TYPE_CIRCLE_WU,                             // Окружность со сглаживанием WU
   
   FIGURE_TYPE_TRIANGLE,                              // Треугольник
   FIGURE_TYPE_TRIANGLE_FILL,                         // Закрашенный треугольник
   FIGURE_TYPE_TRIANGLE_AA,                           // Треугольник со сглаживанием AntiAlliasing
   FIGURE_TYPE_TRIANGLE_WU,                           // Треугольник со сглаживанием WU
   
   FIGURE_TYPE_ELLIPSE,                               // Эллипс
   FIGURE_TYPE_ELLIPSE_FILL,                          // Закрашенный эллипс
   FIGURE_TYPE_ELLIPSE_AA,                            // Эллипс со сглаживанием AntiAlliasing
   FIGURE_TYPE_ELLIPSE_WU,                            // Эллипс со сглаживанием WU
   
   FIGURE_TYPE_ARC,                                   // Дуга эллипса
   FIGURE_TYPE_PIE,                                   // Сектор эллипса
   
  };
//+------------------------------------------------------------------+

Типы кадров анимации будем использовать для идентификации объектов-кадров анимации (текст ли это, рисуемая ли фигура, либо какой-то иной тип кадра анимации, которые далее будем делать в последующих статьях). Типы рисуемых фигур будут указывать нам на то, что именно рисуется в одном кадре прямоугольной анимации. Эти типы соответствуют имеющимся методам рисования в классе CCanvas (разделы "Доступ к данным", "Рисование примитивов", "Рисование закрашенных примитивов" и "Рисование примитивов с использованием сглаживания" в таблице методов класса).

В файле \MQL5\Include\DoEasy\Data.mqh впишем индексы новых сообщений:

//--- CForm
   MSG_FORM_OBJECT_TEXT_NO_SHADOW_OBJ_FIRST_CREATE_IT,// Отсутствует объект тени. Необходимо сначала его создать при помощи метода CreateShadowObj()
   MSG_FORM_OBJECT_ERR_FAILED_CREATE_SHADOW_OBJ,      // Не удалось создать новый объект для тени
   MSG_FORM_OBJECT_ERR_FAILED_CREATE_PC_OBJ,          // Не удалось создать новый объект-копировщик пикселей
   MSG_FORM_OBJECT_PC_OBJ_ALREADY_IN_LIST,            // В списке уже есть объект-копировщик пикселей с идентификатором 
   MSG_FORM_OBJECT_PC_OBJ_NOT_EXIST_LIST,             // В списке нет объекта-копировщика пикселей с идентификатором 

//--- CFrame
   MSG_FORM_OBJECT_ERR_FAILED_CREATE_FRAME,           // Не удалось создать новый объект-кадр анимации
   MSG_FORM_OBJECT_FRAME_ALREADY_IN_LIST,             // В списке уже есть объект-кадр анимации с идентификатором 
   MSG_FORM_OBJECT_FRAME_NOT_EXIST_LIST,              // В списке нет объекта-кадра анимации с идентификатором 

//--- CShadowObj
   MSG_SHADOW_OBJ_IMG_SMALL_BLUR_LARGE,               // Ошибка! Размер изображения очень маленький или очень большое размытие

и тексты сообщений, соответствующие вновь добавленным индексам:

//--- CForm
   {"Отсутствует объект тени. Необходимо сначала его создать при помощи метода CreateShadowObj()","There is no shadow object. You must first create it using the CreateShadowObj () method"},
   {"Не удалось создать новый объект для тени","Failed to create new object for shadow"},
   {"Не удалось создать новый объект-копировщик пикселей","Failed to create new pixel copier object"},
   {"В списке уже есть объект-копировщик пикселей с идентификатором ","There is already a pixel copier object in the list with ID "},
   {"В списке нет объекта-копировщика пикселей с идентификатором ","No pixel copier object with ID "},
   
//--- CFrame
   {"Не удалось создать новый объект-кадр анимации","Failed to create new animation frame object"},
   {"В списке уже есть объект-кадр анимации с идентификатором ","The list already contains an animation frame object with an ID "},
   {"В списке нет объекта-кадра анимации с идентификатором ","No animation frame object with ID "},
   
//--- CShadowObj
   {"Ошибка! Размер изображения очень маленький или очень большое размытие","Error! Image size is very small or very large blur"},


В файл сервисных функций библиотеки \MQL5\Include\DoEasy\Services\DELib.mqh впишем функции, возвращающие максимальное и минимальное значение в массиве:

//+------------------------------------------------------------------+
//| Возвращает максимальное значение в массиве                       |
//+------------------------------------------------------------------+
template<typename T>
bool ArrayMaximumValue(const string source,const T &array[],T &max_value)
  {
   if(ArraySize(array)==0)
     {
      CMessage::ToLog(source,MSG_CANV_ELEMENT_ERR_EMPTY_ARRAY);
      return false;
     }
   max_value=0;
   int index=ArrayMaximum(array);
   if(index==WRONG_VALUE)
      return false;
   max_value=array[index];
   return true;
  }
//+------------------------------------------------------------------+
//| Возвращает минимальное значение в массиве                        |
//+------------------------------------------------------------------+
template<typename T>
bool ArrayMinimumValue(const string source,const T &array[],T &min_value)
  {
   if(ArraySize(array)==0)
     {
      CMessage::ToLog(source,MSG_CANV_ELEMENT_ERR_EMPTY_ARRAY);
      return false;
     }
   min_value=0;
   int index=ArrayMinimum(array);
   if(index==WRONG_VALUE)
      return false;
   min_value=array[index];
   return true;
  }
//+------------------------------------------------------------------+

Функции возвращают максимальное или минимальное значение, находящееся в переданном в них по ссылке массиве, и имеют тип bool по той причине, что любое возвращаемое значение из функции как "ошибочное" может находиться в ячейках массива. Например, если при ошибке получения данных из массива возвращать -1 (как это делается во многих функциях), то такое значение может быть одним из тех, что записаны в массиве. При возврате верно найденного значения (-1) наша программа будет считать, что это ошибка. Это не верно. Поэтому, мы будем при ошибке возвращать false, а само найденное максимальное или минимальное значение в массиве будем записывать в переменную, передаваемую по ссылке в функцию. Если функция возвращает true, то в этой переменной будет храниться искомое значение. В переменной source в функцию передаётся название метода, из которого была вызвана эта функция, что позволит при ошибке вывести название того метода, из которого была вызвана эта функция, и текст сообщения об ошибке.

Туда же впишем функцию, возвращающую описание типа рисуемой фигуры:

//+------------------------------------------------------------------+
//| Возвращает описание типа рисуемой фигуры                         |
//+------------------------------------------------------------------+
string FigureTypeDescription(const ENUM_FIGURE_TYPE figure_type)
  {
   return(StringSubstr(EnumToString(figure_type),12));
  }
//+------------------------------------------------------------------+

Здесь переданный в функцию в формате перечисления тип преобразуется в строковое описание и уже из текстового представления типа извлекается подстрока с позиции 12-го символа для обрезания ненужного текста. Таким образом, например, тип фигуры FIGURE_TYPE_TRIANGLE будет преобразован в текст "FIGURE_TYPE_TRIANGLE" и из этого текста будет извлечена нужная подстрока, начинающаяся с 12-го символа "FIGURE_TYPE_TRIANGLE". В результате будет возвращена строка "TRIANGLE".

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

В файле \MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqh класса графического элемента переименуем метод

//--- Возвращает смещения координат относительно точки привязки текста
   void              TextGetShiftXY(const string text,            // Текст для расчёта размера его очерчивающего прямоугольника
                                    const ENUM_TEXT_ANCHOR anchor,// Точка привязки текста, относительно которой будут рассчитаны смещения
                                    int &shift_x,                 // Сюда будет записана X-координата верхнего левого угла прямоугольника
                                    int &shift_y);                // Сюда будет записана Y-координата верхнего левого угла прямоугольника

Теперь этот метод будет называться GetShiftXYbyText() и объявим новый метод, возвращающий координаты и размер копируемой части изображения по указанному размеру относительно точки привязки объекта:

//--- Возвращает смещения координат относительно точки привязки текста по тексту
   void              GetShiftXYbyText(const string text,             // Текст для расчёта размера его очерчивающего прямоугольника
                                      const ENUM_TEXT_ANCHOR anchor, // Точка привязки текста, относительно которой будут рассчитаны смещения
                                      int &shift_x,                  // Сюда будет записана X-координата верхнего левого угла прямоугольника
                                      int &shift_y);                 // Сюда будет записана Y-координата верхнего левого угла прямоугольника
//--- Возвращает смещения координат относительно точки привязки прямоугольника по размеру
   void              GetShiftXYbySize(const int width,               //Размер прямоугольника по ширине
                                      const int height,              //Размер прямоугольника по высоте
                                      const ENUM_TEXT_ANCHOR anchor, // Точка привязки прямоугольника, относительно которой будут рассчитаны смещения
                                      int &shift_x,                  // Сюда будет записана X-координата верхнего левого угла прямоугольника
                                      int &shift_y);                 // Сюда будет записана Y-координата верхнего левого угла прямоугольника

В конце листинга класса напишем их реализацию.

Метод, возвращающий смещения координат относительно точки привязки прямоугольника по размеру:

//+------------------------------------------------------------------+
//| Возвращает смещения координат относительно точки привязки        |
//| прямоугольника по размеру                                        |
//+------------------------------------------------------------------+
void CGCnvElement::GetShiftXYbySize(const int width,const int height,const ENUM_TEXT_ANCHOR anchor,int &shift_x,int &shift_y)
  {
   switch(anchor)
     {
      case TEXT_ANCHOR_LEFT_TOP        :  shift_x=0;        shift_y=0;           break;
      case TEXT_ANCHOR_LEFT_CENTER     :  shift_x=0;        shift_y=-height/2;   break;
      case TEXT_ANCHOR_LEFT_BOTTOM     :  shift_x=0;        shift_y=-height;     break;
      case TEXT_ANCHOR_CENTER_TOP      :  shift_x=-width/2; shift_y=0;           break;
      case TEXT_ANCHOR_CENTER          :  shift_x=-width/2; shift_y=-height/2;   break;
      case TEXT_ANCHOR_CENTER_BOTTOM   :  shift_x=-width/2; shift_y=-height;     break;
      case TEXT_ANCHOR_RIGHT_TOP       :  shift_x=-width;   shift_y=0;           break;
      case TEXT_ANCHOR_RIGHT_CENTER    :  shift_x=-width;   shift_y=-height/2;   break;
      case TEXT_ANCHOR_RIGHT_BOTTOM    :  shift_x=-width;   shift_y=-height;     break;
      default                          :  shift_x=0;        shift_y=0;           break;
     }
  }
//+------------------------------------------------------------------+

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

Метод, возвращающий смещения координат относительно точки привязки текста:

//+------------------------------------------------------------------+
//| Возвращает смещения координат относительно точки привязки текста |
//+------------------------------------------------------------------+
void CGCnvElement::GetShiftXYbyText(const string text,const ENUM_TEXT_ANCHOR anchor,int &shift_x,int &shift_y)
  {
   int tw=0,th=0;
   this.TextSize(text,tw,th);
   this.GetShiftXYbySize(tw,th,anchor,shift_x,shift_y);
  }
//+------------------------------------------------------------------+

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

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

Итак, создадим базовый класс одного кадра анимации. Класс будет содержать в себе общие для всех своих наследников свойства.

Класс объекта "Кадр анимации"

В папке \MQL5\Include\DoEasy\Objects\Graph\ создадим новую папку Animations\, а в ней — новый файл Frame.mqh класса CFrame.

К файлу класса должен быть подключен файл класса объекта-графического элемента:

//+------------------------------------------------------------------+
//|                                                        Frame.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property strict    // Нужно для mql4
//+------------------------------------------------------------------+
//| Включаемые файлы                                                 |
//+------------------------------------------------------------------+
#include "..\GCnvElement.mqh"
//+------------------------------------------------------------------+

Далее разместим удалённый из файла класса объекта-формы класс объекта-копировщика пикселей (его мы рассматривали в прошлой статье):

//+------------------------------------------------------------------+
//|                                                        Frame.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property strict    // Нужно для mql4
//+------------------------------------------------------------------+
//| Включаемые файлы                                                 |
//+------------------------------------------------------------------+
#include "..\GCnvElement.mqh"
//+------------------------------------------------------------------+
//| Класс копировщика пикселей                                       |
//+------------------------------------------------------------------+
class CPixelCopier : public CObject
  {
protected:
   CGCnvElement     *m_element;                             // Указатель на графический элемент
   uint              m_array[];                             // Массив пикселей
   int               m_id;                                  // Идентификатор
   int               m_x;                                   // Координата X верхнего левого угла
   int               m_y;                                   // Координата Y верхнего левого угла
   int               m_w;                                   // Ширина копируемого изображения
   int               m_h;                                   // Высота копируемого изображения
   int               m_wr;                                  // Рассчитываемая ширина копируемого изображения
   int               m_hr;                                  // Рассчитываемая высота копируемого изображения
public:
//--- Сравнивает объекты CPixelCopier между собой по указанному свойству (для сортировки списка по свойству объекта)
   virtual int       Compare(const CObject *node,const int mode=0) const
                       {
                        const CPixelCopier *obj_compared=node;
                        return(mode==0 ? (this.ID()>obj_compared.ID() ? 1 : this.ID()<obj_compared.ID() ? -1 : 0) : WRONG_VALUE);
                       }
   
//--- Установка свойств
   void              SetElement(CGCnvElement *element)         { this.m_element=element;  }
   void              SetID(const int id)                       { this.m_id=id;            }
   void              SetCoordX(const int value)                { this.m_x=value;          }
   void              SetCoordY(const int value)                { this.m_y=value;          }
   void              SetWidth(const int value)                 { this.m_w=value;          }
   void              SetHeight(const int value)                { this.m_h=value;          }
//--- Получение свойств
   int               ID(void)                            const { return this.m_id;        }
   int               CoordX(void)                        const { return this.m_x;         }
   int               CoordY(void)                        const { return this.m_y;         }
   int               Width(void)                         const { return this.m_w;         }
   int               Height(void)                        const { return this.m_h;         }
   int               WidthReal(void)                     const { return this.m_wr;        }
   int               HeightReal(void)                    const { return this.m_hr;        }

//--- Копирует часть или всё изображение в массив
   bool              CopyImgDataToArray(const uint x_coord,const uint y_coord,uint width,uint height);
//--- Копирует часть или всё изображение из массива на канвас
   bool              CopyImgDataToCanvas(const int x_coord,const int y_coord);

//--- Конструкторы
                     CPixelCopier (void){;}
                     CPixelCopier (const int id,
                                   const int x,
                                   const int y,
                                   const int w,
                                   const int h,
                                   CGCnvElement *element) : m_id(id), m_x(x),m_y(y),m_w(w),m_wr(w),m_h(h),m_hr(h) { this.m_element=element; }
                    ~CPixelCopier (void){;}
  };
//+------------------------------------------------------------------+
//| Копирует часть или всё изображение в массив                      |
//+------------------------------------------------------------------+
bool CPixelCopier::CopyImgDataToArray(const uint x_coord,const uint y_coord,uint width,uint height)
  {
//--- Присваиваем переменным значения координат, переданных в метод
   int x1=(int)x_coord;
   int y1=(int)y_coord;
//--- Если X-координата выходит за пределы формы справа, или Y-координата выходит за пределы снизу,
//--- то копировать нечего - копируемая область за пределами формы - возвращаем false
   if(x1>this.m_element.Width()-1 || y1>this.m_element.Height()-1)
      return false;
//--- Присваиваем переменным значения ширины и высоты копируемой области
//--- Если переданные ширина и высота равны нулю - присваиваем им значения ширины и высоты формы
   this.m_wr=int(width==0  ? this.m_element.Width()  : width);
   this.m_hr=int(height==0 ? this.m_element.Height() : height);

//--- Если координаты X и Y равны нулю (это верхний левый угол формы) и ширина и высота равны ширине и высоте формы,
//--- Значит копируемая область равна всей площади формы - копируем (с возвратом из метода) всю форму целиком при помощи метода ImageCopy()
   //if(x1==0 && y1==0 && this.m_wr==this.m_element.Width() && this.m_hr==this.m_element.Height())
   //   return this.m_element.ImageCopy(DFUN,this.m_array);

//--- Рассчитываем правую координату X и нижнюю координату Y прямоугольной области
   int x2=int(x1+this.m_wr-1);
   int y2=int(y1+this.m_hr-1);
//--- Если рассчитанная координата X выхоит за пределы формы, то этой координатой будет правый край формы
   if(x2>=this.m_element.Width()-1)
      x2=this.m_element.Width()-1;
//--- Если рассчитанная координата Y выхоит за пределы формы, то этой координатой будет нижний край формы
   if(y2>=this.m_element.Height()-1)
      y2=this.m_element.Height()-1;
//--- Рассчитываем копируемые ширину и высоту
   this.m_wr=x2-x1+1;
   this.m_hr=y2-y1+1;
//--- Определяем необходимый размер массива, в который должны поместиться все пиксели изображения с рассчитанными шириной и высотой
   int size=this.m_wr*this.m_hr;
//--- Если размер массива установить не удалось - сообщаем об этом и возвращаем false
   if(::ArrayResize(this.m_array,size)!=size)
     {
      CMessage::ToLog(DFUN,MSG_LIB_SYS_FAILED_ARRAY_RESIZE,true);
      return false;
     }
//--- Устанавливаем индекс в массиве для записи пикселя изображения
   int n=0;
//--- В цикле по рассчитанной высоте копируемой области, начиная от указанной координаты Y
   for(int y=y1;y<y1+this.m_hr;y++)
     {
      //--- в цикле по рассчитанной ширине копируемой области, начиная от указанной координаты X
      for(int x=x1;x<x1+this.m_wr;x++)
        {
         //--- Копируем очередной пиксель изображения в массив и увеличиваем индекс массива
         this.m_array[n]=this.m_element.GetCanvasObj().PixelGet(x,y);
         n++;
        }
     }
//--- Успешно - возвращаем true
   return true;
  }
//+------------------------------------------------------------------+
//| Копирует часть или всё изображение из массива на канвас          |
//+------------------------------------------------------------------+
bool CPixelCopier::CopyImgDataToCanvas(const int x_coord,const int y_coord)
  {
//--- Если массив сохранённых пикселей пустой - сообщаем об этом и возвращаем false
   int size=::ArraySize(this.m_array);
   if(size==0)
     {
      CMessage::ToLog(DFUN,MSG_CANV_ELEMENT_ERR_EMPTY_ARRAY,true);
      return false;
     }
//--- Устанавливаем индекс массива для чтения пикселя изображения
   int n=0;
//--- В цикле по ранее рассчитанной высоте скопированной области, начиная от указанной координаты Y
   for(int y=y_coord;y<y_coord+this.m_hr;y++)
     {
      //--- в цикле по ранее рассчитанной ширине скопированной области, начиная от указанной координаты X
      for(int x=x_coord;x<x_coord+this.m_wr;x++)
        {
         //--- Восстанавливаем очередной пиксель изображения из массива и увеличиваем индекс массива
         this.m_element.GetCanvasObj().PixelSet(x,y,this.m_array[n]);
         n++;
        }
     }
   return true;
  }
//+------------------------------------------------------------------+

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

Далее — после листинга класса-копировщика пикселей, напишем тело класса объекта-кадра анимации:

//+------------------------------------------------------------------+
//| Класс одного кадра анимации                                      |
//+------------------------------------------------------------------+
class CFrame : public CPixelCopier
  {
protected:
   ENUM_ANIMATION_FRAME_TYPE m_frame_figure_type;           // Тип фигуры, рисуемой кадром
   ENUM_TEXT_ANCHOR  m_anchor_last;                         // Точка привязки последнего кадра
   double            m_x_last;                              // Координата X верхнего левого угла последнего кадра
   double            m_y_last;                              // Координата Y верхнего левого угла последнего кадра
   int               m_shift_x_prev;                        // Смещение координаты X верхнего левого угла последнего кадра
   int               m_shift_y_prev;                        // Смещение координаты Y верхнего левого угла последнего кадра
public:
//--- Возвращает последнюю (1) точку привязки, координату (2) X, (3) Y,
//--- предыдущее смещение по (4) X и (5) Y, (6) тип фигуры, рисуемой кадром
   ENUM_TEXT_ANCHOR  LastAnchor(void)                 const { return this.m_anchor_last;        }
   double            LastX(void)                      const { return this.m_x_last;             }
   double            LastY(void)                      const { return this.m_y_last;             }
   int               LastShiftX(void)                 const { return this.m_shift_x_prev;       }
   int               LastShiftY(void)                 const { return this.m_shift_y_prev;       }
   ENUM_ANIMATION_FRAME_TYPE FrameFigureType(void)    const { return this.m_frame_figure_type;  }
   
//--- Конструктор по умолчанию
                     CFrame();
protected:
//--- Конструктор текстового кадра
                     CFrame(const int id,
                            const int x,
                            const int y,
                            const string text,
                            CGCnvElement *element);
//--- Конструктор прямоугольного кадра
                     CFrame(const int id,
                            const int x,
                            const int y,
                            const int w,
                            const int h,
                            CGCnvElement *element);
  };
//+------------------------------------------------------------------+

Класс унаследован от класса объекта-копировщика пикселей, т.е., по сути — является им.

Все переменные и методы, объявленные в классе, описаны в комментариях. Так как этот класс будет базовым для других классов-кадров анимации, то здесь прописаны только все общие для наследников свойства и методы.

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

Класс имеет три конструктора:

  1. публичный конструктор по умолчанию,
  2. защищённый конструктор объекта-текстового кадра,
  3. защищённый конструктор объекта-прямоугольного кадра.

Рассмотрим реализацию защищённых конструкторов.

Конструктор прямоугольных кадров:

//+------------------------------------------------------------------+
//| Конструктор прямоугольных кадров                                 |
//+------------------------------------------------------------------+
CFrame::CFrame(const int id,const int x,const int y,const int w,const int h,CGCnvElement *element) : CPixelCopier(id,x,y,w,h,element)
  {
   this.m_frame_figure_type=ANIMATION_FRAME_TYPE_QUAD;
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=x;
   this.m_y_last=y;
   this.m_shift_x_prev=0;
   this.m_shift_y_prev=0;
  }
//+------------------------------------------------------------------+

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

Конструктор текстовых кадров:

//+------------------------------------------------------------------+
//| Конструктор текстовых кадров                                     |
//+------------------------------------------------------------------+
CFrame::CFrame(const int id,
               const int x,
               const int y,
               const string text,
               CGCnvElement *element)
  {
   int w=0,h=0;
   this.m_element=element;
   this.m_element.GetCanvasObj().TextSize(text,w,h);
   this.m_anchor_last=this.m_element.TextAnchor();
   this.m_frame_figure_type=ANIMATION_FRAME_TYPE_TEXT;
   this.m_x_last=x;
   this.m_y_last=y;
   this.m_shift_x_prev=0;
   this.m_shift_y_prev=0;
   CPixelCopier::SetID(id);
   CPixelCopier::SetCoordX(x);
   CPixelCopier::SetCoordY(y);
   CPixelCopier::SetWidth(w);
   CPixelCopier::SetHeight(h);
  }
//+------------------------------------------------------------------+

В конструктор передаются: идентификатор создаваемого объекта-текстового кадра, его координаты X и Y, текст и указатель на объект-графический элемент, из которого создаётся этот новый объект.
В теле класса сначала определяем размеры текста, затем устанавливаем значения по умолчанию переменным-членам класса и устанавливаем в родительский объект-копировщих пикселей идентификатор создаваемого объекта, его координаты и размер текста.

Создадим классы объектов-наследников класса объекта-кадра анимации.

Класс текстового кадра анимации

В папке \MQL5\Include\DoEasy\Objects\Graph\Animations\ создадим новый файл FrameText.mqh класса CFrameText.

К файлу должен быть подключен файл класса кадра анимации, а сам класс должен быть его наследником:

//+------------------------------------------------------------------+
//|                                                    FrameText.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property strict    // Нужно для mql4
//+------------------------------------------------------------------+
//| Включаемые файлы                                                 |
//+------------------------------------------------------------------+
#include "Frame.mqh"
//+------------------------------------------------------------------+
//| Класс одного кадра текстовой анимации                            |
//+------------------------------------------------------------------+
class CFrameText : public CFrame
  {
private:

public:
//--- Выводит текст на фон с сохранением и восстановлением фона
   bool              TextOnBG(const string text,const int x,const int y,const ENUM_TEXT_ANCHOR anchor,const color clr,const uchar opacity,bool redraw=false);

//--- Конструкторы
                     CFrameText() {;}
                     CFrameText(const int id,CGCnvElement *element) : CFrame(id,0,0,"",element) {}
  };
//+------------------------------------------------------------------+

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

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

Метод, выводящий текст на фон с сохранением и восстановлением фона:

//+------------------------------------------------------------------+
//| Выводит текст на фон с сохранением и восстановлением фона        |
//+------------------------------------------------------------------+
bool CFrameText::TextOnBG(const string text,const int x,const int y,const ENUM_TEXT_ANCHOR anchor,const color clr,const uchar opacity,bool redraw=false)
  {
//--- Узнаем ширину и высоту очерчивающего прямоугольника текста (это и будет размером сохраняемой области)
   int w=0,h=0;
   this.m_element.TextSize(text,w,h);
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки текста
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(w,h,anchor,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под текстом -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим текстом успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(x+shift_x,y+shift_y,w,h))
      return false;
//--- Нарисуем текст и обновим элемент
   this.m_element.Text(x,y,text,clr,opacity,anchor);
   this.m_element.Update(redraw);
   this.m_anchor_last=anchor;
   this.m_x_last=x;
   this.m_y_last=y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Логика метода подробно расписана в комментариях к коду, ранее нами уже рассматривалась в прошлой статье при тестировании (аналогичная логика была прописана в обработчике OnChartEvent() тестового советника) и, надеюсь, здесь вопросов не возникнет. После того, как текст на форме нарисован, его точка привязки, координаты X и Y и размеры смещения относительно точки привязки записываются в переменные родительского класса — их значения будут использоваться для восстановления затёртого текстом фона изображения формы.

Теперь создадим второй класс-наследник объекта-кадра анимации.

Класс прямоугольного кадра анимации

В папке \MQL5\Include\DoEasy\Objects\Graph\Animations\ создадим новый файл FrameQuad.mqh класса CFrameQuad.

К файлу класса должен быть подключен файл родительского класса, и от него же он должен быть унаследован:

//+------------------------------------------------------------------+
//|                                                    FrameQuad.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property strict    // Нужно для mql4
//+------------------------------------------------------------------+
//| Включаемые файлы                                                 |
//+------------------------------------------------------------------+
#include "Frame.mqh"
//+------------------------------------------------------------------+
//| Класс одного кадра спрайтовой анимации                           |
//+------------------------------------------------------------------+
class CFrameQuad : public CFrame
  {
private:
   double            m_quad_x;                                 // X-координата охватывающего фигуру прямоугольника
   double            m_quad_y;                                 // Y-координата охватывающего фигуру прямоугольника
   uint              m_quad_width;                             // Ширина охватывающего фигуру прямоугольника
   uint              m_quad_height;                            // Высота охватывающего фигуру прямоугольника
   
public:

//--- Конструкторы
                     CFrameQuad() {;}
                     CFrameQuad(const int id,CGCnvElement *element) : CFrame(id,0,0,0,0,element) { this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;   }

//+------------------------------------------------------------------+

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

В параметрическом конструкторе передаются идентификатор создаваемого объекта и указатель на графический элемент, из которого создаётся этот объект. В списке инициализации конструктора в конструктор ролительского класса передаётся идентификатор, переданный в аргументах метода, параметры по умолчанию координат и размеров кадра и указатель на графический элемент. В теле конструктора устанавливаем точку привязки рисуемой фигуры как "сверху-слева" — это необходимо будет для расчёта смещения копируемой области. При таком значении точки привязки смещения координат по X и Y будут нулевыми.

Так как методов рисования в классе CCanvas достаточно много, то у нас в этом классе, в его публичной секции будут объявлены все соответствующие методы для рисования фигур на фоне объекта-формы с последующим восстановлением фона:

public:

//--- Конструкторы
                     CFrameQuad() {;}
                     CFrameQuad(const int id,CGCnvElement *element) : CFrame(id,0,0,0,0,element) { this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;   }

//+------------------------------------------------------------------+
//| Рисование примитивов с сохранением и восстановлением фона        |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Методы рисования примитивов без сглаживания                      |
//+------------------------------------------------------------------+
//--- Устанавливает цвет точки с указанными координатами
   bool              SetPixelOnBG(const int x,const int y,const color clr,const uchar opacity=255,const bool redraw=false);
                       
//--- Рисует отрезок вертикальной линии
   bool              DrawLineVerticalOnBG(const int x,                  // Координата X отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует отрезок горизонтальной линии
   bool              DrawLineHorizontalOnBG(const int x1,               // Координата X первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y,                            // Координата Y отрезка
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует отрезок произвольной линии
   bool              DrawLineOnBG(const int x1,                         // Координата X первой точки отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует ломаную линию
   bool              DrawPolylineOnBG(int &array_x[],                   // Массив координат X точек ломаной линии
                              int         &array_y[],                   // Массив координат Y точек ломаной линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует многоугольник
   bool              DrawPolygonOnBG(int  &array_x[],                   // Массив координат X точек многоугольника
                              int         &array_y[],                   // Массив координат Y точек многоугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует прямоугольник по двум точкам
   bool              DrawRectangleOnBG(const int x1,                    // Координата X первой точки, определяющей прямоугольник
                              const int   y1,                           // Координата Y первой точки, определяющей прямоугольник
                              const int   x2,                           // Координата X второй точки, определяющей прямоугольник
                              const int   y2,                           // Координата Y второй точки, определяющей прямоугольник
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует окружность
   bool              DrawCircleOnBG(const int x,                        // Координата X центра окружности
                              const int   y,                            // Координата Y центра окружности
                              const int   r,                            // Радиус окружности
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует треугольник
   bool              DrawTriangleOnBG(const int x1,                     // Координата X первой вершины треугольника
                              const int   y1,                           // Координата Y первой вершины треугольника
                              const int   x2,                           // Координата X второй вершины треугольника
                              const int   y2,                           // Координата Y второй вершины треугольника
                              const int   x3,                           // Координата X третьей вершины треугольника
                              const int   y3,                           // Координата Y третьей вершины треугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует эллипс по двум точкам
   bool              DrawEllipseOnBG(const int x1,                      // Координата X первой точки, определяющей эллипс
                              const int   y1,                           // Координата Y первой точки, определяющей эллипс
                              const int   x2,                           // Координата X второй точки, определяющей эллипс
                              const int   y2,                           // Координата Y второй точки, определяющей эллипс
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует дугу эллипса, вписанного в прямоугольник с углами в (x1,y1) и (x2,y2).
//--- Границы дуги отсекаются линиями из центра эллипса, идущими к двум точкам с координатами (x3,y3) и (x4,y4)
   bool              DrawArcOnBG(const int x1,                          // Координата X левого верхнего угла, определяющего прямоугольник
                              const int   y1,                           // Координата Y левого верхнего угла, определяющего прямоугольник
                              const int   x2,                           // Координата X правого нижнего угла, определяющего прямоугольник
                              const int   y2,                           // Координата Y правого нижнего угла, определяющего прямоугольник
                              const int   x3,                           // Координата X первой точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                              const int   y3,                           // Координата Y первой точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                              const int   x4,                           // Координата X второй точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                              const int   y4,                           // Координата Y второй точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует закрашенный сектор эллипса, вписанного в прямоугольник с углами в (x1,y1) и (x2,y2).
//--- Границы сектора отсекаются линиями из центра эллипса, идущими к двум точкам с координатами (x3,y3) и (x4,y4)
   bool              DrawPieOnBG(const int x1,                          // координата X верхнего левого угла прямоугольника
                              const int   y1,                           // координата Y верхнего левого угла прямоугольника
                              const int   x2,                           // координата X нижнего правого угла прямоугольника
                              const int   y2,                           // координата Y нижнего правого угла прямоугольника
                              const int   x3,                           // координата X первой точки для нахождения границы дуги
                              const int   y3,                           // координата Y первой точки для нахождения границы дуги
                              const int   x4,                           // координата X второй точки для нахождения границы дуги
                              const int   y4,                           // координата Y второй точки для нахождения границы дуги
                              const color clr,                          // Цвет линии
                              const color fill_clr,                     // Цвет заливки
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//+------------------------------------------------------------------+
//| Методы рисования закрашенных примитивов без сглаживания          |
//+------------------------------------------------------------------+
//--- Закрашивает область
   bool              FillOnBG(const int   x,                            // Координата X точки начала закрашивания
                              const int   y,                            // Координата Y точки начала закрашивания
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const uint  threshould=0,                 // Порог
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует закрашенный прямоугольник
   bool              DrawRectangleFillOnBG(const int x1,                // Координата X первой точки, определяющей прямоугольник
                              const int   y1,                           // Координата Y первой точки, определяющей прямоугольник
                              const int   x2,                           // Координата X второй точки, определяющей прямоугольник
                              const int   y2,                           // Координата Y второй точки, определяющей прямоугольник
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта

//--- Рисует закрашенный круг
   bool              DrawCircleFillOnBG(const int x,                    // Координата X центра круга
                              const int   y,                            // Координата Y центра круга
                              const int   r,                            // Радиус круга
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует закрашенный треугольник
   bool              DrawTriangleFillOnBG(const int x1,                 // Координата X первой вершины треугольника
                              const int   y1,                           // Координата Y первой вершины треугольника
                              const int   x2,                           // Координата X второй вершины треугольника
                              const int   y2,                           // Координата Y второй вершины треугольника
                              const int   x3,                           // Координата X третьей вершины треугольника
                              const int   y3,                           // Координата Y третьей вершины треугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует закрашенный многоугольник
   bool              DrawPolygonFillOnBG(int &array_x[],                // Массив, содержащий координаты X точек многоугольника
                              int         &array_y[],                   // Массив, содержащий координаты Y точек многоугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует закрашенный эллипс, вписанный в прямоугольник с заданными координатами
   bool              DrawEllipseFillOnBG(const int x1,                  // Координата X левого верхнего угла, определяющего прямоугольник
                              const int   y1,                           // Координата Y левого верхнего угла, определяющего прямоугольник
                              const int   x2,                           // Координата X правого нижнего угла, определяющего прямоугольник
                              const int   y2,                           // Координата Y правого нижнего угла, определяющего прямоугольник
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//+------------------------------------------------------------------+
//| Методы рисования примитивов с использованием сглаживания         |
//+------------------------------------------------------------------+
//--- Рисует точку с использованием алгоритма сглаживания AntiAliasing
   bool              SetPixelAAOnBG(const double x,                     // Координата X точки
                              const double y,                           // Координата Y точки
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const bool   redraw=false);               // Флаг перерисовки чарта
                       
//--- Рисует отрезок произвольной линии с использованием алгоритма сглаживания AntiAliasing
   bool              DrawLineAAOnBG(const int x1,                       // Координата X первой точки отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует отрезок произвольной линии с использованием алгоритма сглаживания Wu
   bool              DrawLineWuOnBG(const int x1,                       // Координата X первой точки отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует отрезок произвольной линии заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
   bool              DrawLineThickOnBG(const int x1,                    // Координата X первой точки отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const int   size,                         // Толщина линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=STYLE_SOLID,            // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              ENUM_LINE_END end_style=LINE_END_ROUND);  // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
 
//--- Рисует вертикальный отрезок произвольной линии заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
   bool              DrawLineThickVerticalOnBG(const int x,             // Координата X отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const int   size,                         // толщина линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=STYLE_SOLID,            // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              const ENUM_LINE_END end_style=LINE_END_ROUND); // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
                       
//--- Рисует горизонтальный отрезок произвольной линии заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
   bool              DrawLineThickHorizontalOnBG(const int x1,          // Координата X первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y,                            // Координата Y отрезка
                              const int   size,                         // толщина линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=STYLE_SOLID,            // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              const ENUM_LINE_END end_style=LINE_END_ROUND); // Стиль концов линии — одно из значений перечисления ENUM_LINE_END

//--- Рисует ломаную линию с использованием алгоритма сглаживания AntiAliasing
   bool              DrawPolylineAAOnBG(int &array_x[],                 // Массив координат X точек ломаной линии
                              int         &array_y[],                   // Массив координат Y точек ломаной линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует ломаную линию с использованием алгоритма сглаживания Wu
   bool              DrawPolylineWuOnBG(int &array_x[],                 // Массив координат X точек ломаной линии
                              int         &array_y[],                   // Массив координат Y точек ломаной линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует ломаную линию заданной толщины с использованием двух алгоритмов сглаживания последовательно.
//--- Сначала на основе кривых Безье сглаживаются отдельные отрезки линии.
//--- Затем для повышения качества отрисовки к построенной из этих отрезков ломаной линии применяется растровый алгоритм сглаживания
   bool              DrawPolylineSmoothOnBG(const int &array_x[],       // Массив координат X точек ломаной линии
                              const int    &array_y[],                  // Массив координат Y точек ломаной линии
                              const int    size,                        // Толщина линии
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const double tension=0.5,                 // Значение параметра сглаживания
                              const double step=10,                     // Шаг аппроксимации
                              const bool   redraw=false,                // Флаг перерисовки чарта
                              const ENUM_LINE_STYLE style=STYLE_SOLID,  // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              const ENUM_LINE_END   end_style=LINE_END_ROUND);// Стиль концов линии — одно из значений перечисления ENUM_LINE_END
                       
//--- Рисует ломаную линию заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
   bool              DrawPolylineThickOnBG(const int &array_x[],        // Массив координат X точек ломаной линии
                              const int      &array_y[],                // Массив координат Y точек ломаной линии
                              const int      size,                      // Толщина линии
                              const color    clr,                       // Цвет
                              const uchar    opacity=255,               // Непрозрачность
                              const bool     redraw=false,              // Флаг перерисовки чарта
                              const uint     style=STYLE_SOLID,         // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              ENUM_LINE_END  end_style=LINE_END_ROUND); // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
                       
//--- Рисует многоугольник с использованием алгоритма сглаживания AntiAliasing
   bool              DrawPolygonAAOnBG(int &array_x[],                  // Массив координат X точек многоугольника
                              int         &array_y[],                   // Массив координат Y точек многоугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует многоугольник с использованием алгоритма сглаживания Wu
   bool              DrawPolygonWuOnBG(int &array_x[],                  // Массив координат X точек многоугольника
                              int         &array_y[],                   // Массив координат Y точек многоугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует  многоугольник заданной толщины с использованием двух алгоритмов сглаживания последовательно.
//--- Сначала на основе кривых Безье сглаживаются отдельные отрезки.
//--- Затем для повышения качества отрисовки к построенному из этих отрезков многоугольнику применяется растровый алгоритм сглаживания. 
   bool              DrawPolygonSmoothOnBG(int &array_x[],              // Массив координат X точек ломаной линии
                              int          &array_y[],                  // Массив координат Y точек ломаной линии
                              const int    size,                        // Толщина линии
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const double tension=0.5,                 // Значение параметра сглаживания
                              const double step=10,                     // Шаг аппроксимации
                              const bool   redraw=false,                // Флаг перерисовки чарта
                              const ENUM_LINE_STYLE style=STYLE_SOLID,  // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              const ENUM_LINE_END   end_style=LINE_END_ROUND);// Стиль концов линии — одно из значений перечисления ENUM_LINE_END
                       
//--- Рисует многоугольник заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
   bool              DrawPolygonThickOnBG(const int &array_x[],         // массив координат X точек многоугольника
                              const int   &array_y[],                   // массив координат Y точек многоугольника
                              const int   size,                         // толщина линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=STYLE_SOLID,            // стиль линии
                              ENUM_LINE_END end_style=LINE_END_ROUND);  // стиль концов линии
                       
//--- Рисует треугольник с использованием алгоритма сглаживания AntiAliasing
   bool              DrawTriangleAAOnBG(const int x1,                   // Координата X первой вершины треугольника
                              const int   y1,                           // Координата Y первой вершины треугольника
                              const int   x2,                           // Координата X второй вершины треугольника
                              const int   y2,                           // Координата Y второй вершины треугольника
                              const int   x3,                           // Координата X третьей вершины треугольника
                              const int   y3,                           // Координата Y третьей вершины треугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует треугольник с использованием алгоритма сглаживания Wu
   bool              DrawTriangleWuOnBG(const int x1,                   // Координата X первой вершины треугольника
                              const int   y1,                           // Координата Y первой вершины треугольника
                              const int   x2,                           // Координата X второй вершины треугольника
                              const int   y2,                           // Координата Y второй вершины треугольника
                              const int   x3,                           // Координата X третьей вершины треугольника
                              const int   y3,                           // Координата Y третьей вершины треугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует окружность с использованием алгоритма сглаживания AntiAliasing
   bool              DrawCircleAAOnBG(const int x,                      // Координата X центра окружности
                              const int    y,                           // Координата Y центра окружности
                              const double r,                           // Радиус окружности
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const bool   redraw=false,                // Флаг перерисовки чарта
                              const uint   style=UINT_MAX);             // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует окружность с использованием алгоритма сглаживания Wu
   bool              DrawCircleWuOnBG(const int x,                      // Координата X центра окружности
                              const int    y,                           // Координата Y центра окружности
                              const double r,                           // Радиус окружности
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const bool   redraw=false,                // Флаг перерисовки чарта
                              const uint   style=UINT_MAX);             // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует эллипс по двум точкам с использованием алгоритма сглаживания AntiAliasing
   bool              DrawEllipseAAOnBG(const double x1,                 // Координата X первой точки, определяющей эллипс
                              const double y1,                          // Координата Y первой точки, определяющей эллипс
                              const double x2,                          // Координата X второй точки, определяющей эллипс
                              const double y2,                          // Координата Y второй точки, определяющей эллипс
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const bool   redraw=false,                // Флаг перерисовки чарта
                              const uint   style=UINT_MAX);             // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует эллипс по двум точкам с использованием алгоритма сглаживания Wu
   bool              DrawEllipseWuOnBG(const int x1,                    // Координата X первой точки, определяющей эллипс
                              const int   y1,                           // Координата Y первой точки, определяющей эллипс
                              const int   x2,                           // Координата X второй точки, определяющей эллипс
                              const int   y2,                           // Координата Y второй точки, определяющей эллипс
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  };
//+------------------------------------------------------------------+

Реализация всех этих методов, каждого по отдельности, будет похожа на реализацию других таких же методов рисования, но практически каждый из них будет иметь свои нюансы, присущие его методу рисования (размеры сохраняемой области могут отличаться в двух похожих методах рисования из-за особенностей каждого отдельного метода рисования).

Рассмотрим реализацию этих методов.

Метод, устанавливающий цвет точки с указанными координатами:

//+------------------------------------------------------------------+
//| Устанавливает цвет точки с указанными координатами               |
//+------------------------------------------------------------------+
bool CFrameQuad::SetPixelOnBG(const int x,const int y,const color clr,const uchar opacity=255,const bool redraw=false)
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=1;
   this.m_quad_height=1;
   
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.SetPixel(x,y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Логика метода достаточно подробно прокомментирована в коде. Поясню немного подробнее. Здесь мы сначала устанавливаем координаты X и Y левого-верхнего края прямоугольной области фона, которую нужно сохранить в массиве для последующего восстановления фона под нарисованной точкой. Так как это лишь точка (один пиксель изображения), то координаты сохраняемой области совпадают с координатами рисуемой точки, и размеры соответствуют размерам одного пикселя, т.е. 1 x 1.

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

Метод, рисующий отрезок вертикальной линии:

//+------------------------------------------------------------------+
//| Рисует отрезок вертикальной линии                                |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineVerticalOnBG(const int   x,              // Координата X отрезка
                                      const int   y1,             // Координата Y первой точки отрезка
                                      const int   y2,             // Координата Y второй точки отрезка
                                      const color clr,            // Цвет
                                      const uchar opacity=255,    // Непрозрачность
                                      const bool  redraw=false)   // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=x;
   this.m_quad_y=::fmin(y1,y2);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawLineVertical(x,y1,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Здесь уже расчёт координат и размеров очерчивающего фигуру прямоугольника отличается от такого расчёта в предыдущем методе. И это естественно — здесь мы рисуем вертикальную линию шириной в один пиксель. А вот высота этой линии уже должна быть рассчитана как разница между максимальным и минимальным значениями двух Y-координат этой линии. Координата Y сохраняемой области должна соответствовать минимальному значению двух Y-координат (самая верхняя точка рисуемой линии).

Метод, рисующий отрезок горизонтальной линии:

//+------------------------------------------------------------------+
//| Рисует отрезок горизонтальной линии                              |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineHorizontalOnBG(const int   x1,           // Координата X первой точки отрезка
                                        const int   x2,           // Координата X второй точки отрезка
                                        const int   y,            // Координата Y отрезка
                                        const color clr,          // Цвет
                                        const uchar opacity=255,  // Непрозрачность
                                        const bool  redraw=false) // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawLineHorizontal(x1,x2,y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Здесь расчёт координат и размеров сохраняемой области похож на такой же расчёт в предыдущем методе, но с разницей, что это горизонтальная линия, и тут высота равна одному пикселю, а ширина и координата X сохраняемой области должны быть рассчитаны.

Метод, рисующий отрезок произвольной линии:

//+------------------------------------------------------------------+
//| Рисует отрезок произвольной линии                                |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineOnBG(const int   x1,            // Координата X первой точки отрезка
                              const int   y1,            // Координата Y первой точки отрезка
                              const int   x2,            // Координата X второй точки отрезка
                              const int   y2,            // Координата Y второй точки отрезка
                              const color clr,           // Цвет
                              const uchar opacity=255,   // Непрозрачность
                              const bool  redraw=false)  // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawLine(x1,y1,x2,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Здесь уже координаты и размер сохраняемой области рассчитываются от координат рисуемой линии.

Метод, рисующий ломаную линию:

//+------------------------------------------------------------------+
//| Рисует ломаную линию                                             |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolylineOnBG(int         &array_x[],   // Массив координат X точек ломаной линии
                                  int         &array_y[],   // Массив координат Y точек ломаной линии
                                  const color clr,          // Цвет
                                  const uchar opacity=255,  // Непрозрачность
                                  const bool  redraw=false) // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   this.m_quad_height=(max_y_value-min_y_value)+1;

//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolyline(array_x,array_y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Тут расчёт координат и размеров сохраняемой области смысл имеет тот же, но отличается по исполнению от вышерассмотренных методов по причине, что для ломаной линии (как и для многих других фигур) координаты передаются не переменными, а в массивах — ведь тут заранее нельзя знать, сколько изломов будет у линии и сколько координат передавать в аргументах метода. Поэтому перед вызовом метода необходимо заполнить два массива с координатами X и соответствующим им координатам Y каждой точки излома линии.
В методе же мы получаем максимальные и минимальные значения из этих массивов при помощи ранее рассмотренной функции, возвращающей из переданного в неё массива минимальное или максимальное значение, записанное в массиве. И полученные значения используем для расчёта координат и размеров сохраняемой области фона формы.

Остальные методы рисования фигур без сглаживания (просто обратите внимание на расчёты координат и размеров сохраняемой области):

//+------------------------------------------------------------------+
//| Рисует многоугольник                                             |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonOnBG(int         &array_x[],    // Массив координат X точек многоугольника
                                 int         &array_y[],    // Массив координат Y точек многоугольника
                                 const color clr,           // Цвет
                                 const uchar opacity=255,   // Непрозрачность
                                 const bool  redraw=false)  // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   if(this.m_quad_width==0)
      this.m_quad_width=1;
   this.m_quad_height=(max_y_value-min_y_value)+1;
   if(this.m_quad_height==0)
      this.m_quad_height=1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolygon(array_x,array_y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует прямоугольник по двум точкам                              |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawRectangleOnBG(const int   x1,             // Координата X первой точки, определяющей прямоугольник
                                   const int   y1,             // Координата Y первой точки, определяющей прямоугольник
                                   const int   x2,             // Координата X второй точки, определяющей прямоугольник
                                   const int   y2,             // Координата Y второй точки, определяющей прямоугольник
                                   const color clr,            // Цвет
                                   const uchar opacity=255,    // Непрозрачность
                                   const bool  redraw=false)   // Флаг перерисовки чарта
     {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawRectangle(x1,y1,x2,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует окружность                                                |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawCircleOnBG(const int   x,              // Координата X центра окружности
                                const int   y,              // Координата Y центра окружности
                                const int   r,              // Радиус окружности
                                const color clr,            // Цвет
                                const uchar opacity=255,    // Непрозрачность
                                const bool  redraw=false)   // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   int rd=(r>0 ? r : 1);
   this.m_quad_x=x-rd;
   this.m_quad_y=y-rd;
   double x2=x+rd;
   double y2=y+rd;
   if(this.m_quad_x<0)
      this.m_quad_x=0;
   if(this.m_quad_y<0)
      this.m_quad_y=0;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=int(::ceil(x2-this.m_quad_x)+1);
   this.m_quad_height=int(::ceil(y2-this.m_quad_y)+1);
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawCircle(x,y,rd,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_CENTER;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует треугольник                                               |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawTriangleOnBG(const int   x1,           // Координата X первой вершины треугольника
                                  const int   y1,           // Координата Y первой вершины треугольника
                                  const int   x2,           // Координата X второй вершины треугольника
                                  const int   y2,           // Координата Y второй вершины треугольника
                                  const int   x3,           // Координата X третьей вершины треугольника
                                  const int   y3,           // Координата Y третьей вершины треугольника
                                  const color clr,          // Цвет
                                  const uchar opacity=255,  // Непрозрачность
                                  const bool  redraw=false) // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(::fmin(x1,x2),x3);
   this.m_quad_y=::fmin(::fmin(y1,y2),y3);
   int max_x=::fmax(::fmax(x1,x2),x3);
   int max_y=::fmax(::fmax(y1,y2),y3);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=int(max_x-this.m_quad_x)+1;
   this.m_quad_height=int(max_y-this.m_quad_y)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawTriangle(x1,y1,x2,y2,x3,y3,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует эллипс по двум точкам                                     |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawEllipseOnBG(const int   x1,            // Координата X первой точки, определяющей эллипс
                                 const int   y1,            // Координата Y первой точки, определяющей эллипс
                                 const int   x2,            // Координата X второй точки, определяющей эллипс
                                 const int   y2,            // Координата Y второй точки, определяющей эллипс
                                 const color clr,           // Цвет
                                 const uchar opacity=255,   // Непрозрачность
                                 const bool  redraw=false)  // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawEllipse(x1,y1,x2,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует дугу эллипса, вписанного в прямоугольник                  |
//| с углами в (x1,y1) и (x2,y2).                                    |
//| Границы дуги отсекаются линиями из центра эллипса,               |
//| идущими к двум точкам с координатами (x3,y3) и (x4,y4)           |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawArcOnBG(const int   x1,             // Координата X левого верхнего угла, определяющего прямоугольник
                             const int   y1,             // Координата Y левого верхнего угла, определяющего прямоугольник
                             const int   x2,             // Координата X правого нижнего угла, определяющего прямоугольник
                             const int   y2,             // Координата Y правого нижнего угла, определяющего прямоугольник
                             const int   x3,             // Координата X первой точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                             const int   y3,             // Координата Y первой точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                             const int   x4,             // Координата X второй точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                             const int   y4,             // Координата Y второй точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                             const color clr,            // Цвет
                             const uchar opacity=255,    // Непрозрачность
                             const bool  redraw=false)   // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2)-1;
   this.m_quad_y=::fmin(y1,y2)-1;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+2;
   this.m_quad_height=::fabs(y2-y1)+2;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawArc(x1,y1,x2,y2,x3,y3,x4,y4,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный сектор эллипса, вписанного в прямоугольник    |
//| с углами в (x1,y1) и (x2,y2).                                    |
//| Границы сектора отсекаются линиями из центра эллипса,            |
//| идущими к двум точкам с координатами (x3,y3) и (x4,y4)           |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPieOnBG(const int   x1,             // координата X верхнего левого угла прямоугольника
                             const int   y1,             // координата Y верхнего левого угла прямоугольника
                             const int   x2,             // координата X нижнего правого угла прямоугольника
                             const int   y2,             // координата Y нижнего правого угла прямоугольника
                             const int   x3,             // координата X первой точки для нахождения границы дуги
                             const int   y3,             // координата Y первой точки для нахождения границы дуги
                             const int   x4,             // координата X второй точки для нахождения границы дуги
                             const int   y4,             // координата Y второй точки для нахождения границы дуги
                             const color clr,            // Цвет
                             const color fill_clr,       // Цвет заливки
                             const uchar opacity=255,    // Непрозрачность
                             const bool  redraw=false)   // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2)-1;
   this.m_quad_y=::fmin(y1,y2)-1;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+2;
   this.m_quad_height=::fabs(y2-y1)+2;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPie(x1,y1,x2,y2,x3,y3,x4,y4,clr,fill_clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+


Рассмотрим методы рисования закрашенных примитивов без сглаживания.

Метод, закрашивающий область:

//+------------------------------------------------------------------+
//| Закрашивает область                                              |
//+------------------------------------------------------------------+
bool CFrameQuad::FillOnBG(const int   x,              // Координата X точки начала закрашивания
                          const int   y,              // Координата Y точки начала закрашивания
                          const color clr,            // Цвет
                          const uchar opacity=255,    // Непрозрачность
                          const uint  threshould=0,   // Порог
                          const bool  redraw=false)   // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=0;
   this.m_quad_y=0;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=0;
   this.m_quad_height=0;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.Fill(x,y,clr,opacity,threshould);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

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

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

//+------------------------------------------------------------------+
//| Рисует закрашенный прямоугольник                                 |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawRectangleFillOnBG(const int   x1,            // Координата X первой точки, определяющей прямоугольник
                                       const int   y1,            // Координата Y первой точки, определяющей прямоугольник
                                       const int   x2,            // Координата X второй точки, определяющей прямоугольник
                                       const int   y2,            // Координата Y второй точки, определяющей прямоугольник
                                       const color clr,           // Цвет
                                       const uchar opacity=255,   // Непрозрачность
                                       const bool  redraw=false)  // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawRectangleFill(x1,y1,x2,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный круг                                          |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawCircleFillOnBG(const int   x,             // Координата X центра круга
                                    const int   y,             // Координата Y центра круга
                                    const int   r,             // Радиус круга
                                    const color clr,           // Цвет
                                    const uchar opacity=255,   // Непрозрачность
                                    const bool  redraw=false)  // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   int rd=(r>0 ? r : 1);
   this.m_quad_x=x-rd;
   this.m_quad_y=y-rd;
   double x2=x+rd;
   double y2=y+rd;
   if(this.m_quad_x<0)
      this.m_quad_x=0;
   if(this.m_quad_y<0)
      this.m_quad_y=0;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=int(::ceil(x2-this.m_quad_x)+1);
   this.m_quad_height=int(::ceil(y2-this.m_quad_y)+1);
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawCircleFill(x,y,rd,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный треугольник                                   |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawTriangleFillOnBG(const int   x1,             // Координата X первой вершины треугольника
                                      const int   y1,             // Координата Y первой вершины треугольника
                                      const int   x2,             // Координата X второй вершины треугольника
                                      const int   y2,             // Координата Y второй вершины треугольника
                                      const int   x3,             // Координата X третьей вершины треугольника
                                      const int   y3,             // Координата Y третьей вершины треугольника
                                      const color clr,            // Цвет
                                      const uchar opacity=255,    // Непрозрачность
                                      const bool  redraw=false)   // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(::fmin(x1,x2),x3)-1;
   this.m_quad_y=::fmin(::fmin(y1,y2),y3)-1;
   int max_x=::fmax(::fmax(x1,x2),x3)+1;
   int max_y=::fmax(::fmax(y1,y2),y3)+1;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=int(max_x-this.m_quad_x)+1;
   this.m_quad_height=int(max_y-this.m_quad_y)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawTriangleFill(x1,y1,x2,y2,x3,y3,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный многоугольник                                 |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonFillOnBG(int         &array_x[],   // Массив, содержащий координаты X точек многоугольника
                                     int         &array_y[],   // Массив, содержащий координаты Y точек многоугольника
                                     const color clr,          // Цвет
                                     const uchar opacity=255,  // Непрозрачность
                                     const bool  redraw=false) // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   this.m_quad_height=(max_y_value-min_y_value)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolygonFill(array_x,array_y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный эллипс, вписанный в прямоугольник             |
//| с заданными координатами                                         |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawEllipseFillOnBG(const int   x1,           // Координата X левого верхнего угла, определяющего прямоугольник
                                     const int   y1,           // Координата Y левого верхнего угла, определяющего прямоугольник
                                     const int   x2,           // Координата X правого нижнего угла, определяющего прямоугольник
                                     const int   y2,           // Координата Y правого нижнего угла, определяющего прямоугольник
                                     const color clr,          // Цвет
                                     const uchar opacity=255,  // Непрозрачность
                                     const bool  redraw=false) // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawEllipseFill(x1,y1,x2,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+


Методы рисования примитивов со сглаживанием.

Метод, рисующий точку с использованием алгоритма сглаживания AntiAliasing:

//+------------------------------------------------------------------+
//| Рисует точку с использованием алгоритма сглаживания AntiAliasing |
//+------------------------------------------------------------------+
bool CFrameQuad::SetPixelAAOnBG(const double x,             // Координата X точки
                                const double y,             // Координата Y точки
                                const color  clr,           // Цвет
                                const uchar  opacity=255,   // Непрозрачность
                                const bool   redraw=false)  // Флаг перерисовки чарта
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=x-1;
   if(this.m_quad_x<0)
      this.m_quad_x=0;
   this.m_quad_y=y-1;
   if(this.m_quad_y<0)
      this.m_quad_y=0;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=3;
   this.m_quad_height=3;
   
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.SetPixelAA(x,y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Здесь расчёт координат и размеров сохраняемой области отличается от такого расчёта в методе рисования точки без сглаживания. Сглаженная точка может располагаться на трёх смежных пикселях (всего 9, т.е, 3 x 3 пикселя), поэтому и размеры сохраняемой области должны иметь по три пикселя в высоту и ширину. Координаты X и Y, соответственно, должны быть на один пиксель левее и выше координат самой точки. Таким образом, очерчивающий точку прямоугольник сохраняемой области будет иметь запас в один пиксель со всех сторон от рисуемой точки для случая, если нарисованная точка будет размыта алгоритмом сглаживания и нарисована не на одном пикселе. Тем самым мы избавимся от неполного восстановления фона, затёртого нарисованной точкой со сглаживанием.

Метод, рисующий отрезок произвольной линии с использованием алгоритма сглаживания AntiAliasing:

//+------------------------------------------------------------------+
//| Рисует отрезок произвольной линии                                |
//| с использованием алгоритма сглаживания AntiAliasing              |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineAAOnBG(const int   x1,             // Координата X первой точки отрезка
                                const int   y1,             // Координата Y первой точки отрезка
                                const int   x2,             // Координата X второй точки отрезка
                                const int   y2,             // Координата Y второй точки отрезка
                                const color clr,            // Цвет
                                const uchar opacity=255,    // Непрозрачность
                                const bool  redraw=false,   // Флаг перерисовки чарта
                                const uint  style=UINT_MAX) // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;

//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;

//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawLineAA(x1,y1,x2,y2,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Тестирование этого метода показало, что края нарисованной линии не оказываются размытыми, поэтому здесь расчёт размеров сохраняемой области совпадает с расчётом в методе рисования линии без сглаживания.

Метод, рисующий отрезок произвольной линии с использованием алгоритма сглаживания Wu:

//+------------------------------------------------------------------+
//| Рисует отрезок произвольной линии с использованием               |
//| алгоритма сглаживания Wu                                         |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineWuOnBG(const int   x1,             // Координата X первой точки отрезка
                                const int   y1,             // Координата Y первой точки отрезка
                                const int   x2,             // Координата X второй точки отрезка
                                const int   y2,             // Координата Y второй точки отрезка
                                const color clr,            // Цвет
                                const uchar opacity=255,    // Непрозрачность
                                const bool  redraw=false,   // Флаг перерисовки чарта
                                const uint  style=UINT_MAX) // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawLineWu(x1,y1,x2,y2,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Здесь расчёт аналогичен предыдущему методу по той же причине.

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

//+------------------------------------------------------------------+
//| Рисует отрезок произвольной линии заданной толщины               |
//| с использованием алгоритма сглаживания                           |
//| с предварительной фильтрацией                                    |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineThickOnBG(const int   x1,                         // Координата X первой точки отрезка
                                   const int   y1,                         // Координата Y первой точки отрезка
                                   const int   x2,                         // Координата X второй точки отрезка
                                   const int   y2,                         // Координата Y второй точки отрезка
                                   const int   size,                       // Толщина линии
                                   const color clr,                        // Цвет
                                   const uchar opacity=255,                // Непрозрачность
                                   const bool  redraw=false,               // Флаг перерисовки чарта
                                   const uint  style=STYLE_SOLID,          // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                                   ENUM_LINE_END end_style=LINE_END_ROUND) // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
//--- Рассчитаем корректировку координат очерчивающего прямоугольника в зависимости от размера линии
   int correct=int(::ceil((double)size/2.0))+1;
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2)-correct;
   this.m_quad_y=::fmin(y1,y2)-correct;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1+correct*2;
   this.m_quad_height=::fabs(y2-y1)+1+correct*2;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawLineThick(x1,y1,x2,y2,size,clr,opacity,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

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

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

//+------------------------------------------------------------------+
//| Рисует вертикальный отрезок произвольной линии заданной толщины  |
//| с использованием алгоритма сглаживания                           |
//| с предварительной фильтрацией                                    |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineThickVerticalOnBG(const int   x,                              // Координата X отрезка
                                           const int   y1,                             // Координата Y первой точки отрезка
                                           const int   y2,                             // Координата Y второй точки отрезка
                                           const int   size,                           // толщина линии
                                           const color clr,                            // Цвет
                                           const uchar opacity=255,                    // Непрозрачность
                                           const bool  redraw=false,                   // Флаг перерисовки чарта
                                           const uint  style=STYLE_SOLID,              // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                                           const ENUM_LINE_END end_style=LINE_END_ROUND)// Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
//--- Рассчитаем корректировку координат очерчивающего прямоугольника в зависимости от размера линии и типа её окончаний
   int correct_x=(int)::ceil((double)size/2.0);
   int correct_y=(end_style==LINE_END_BUTT ? 0 : correct_x);
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=x-correct_x;
   this.m_quad_y=::fmin(y1,y2)-correct_y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=size;
   this.m_quad_height=::fabs(y2-y1)+1+correct_y*2;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawLineThickVertical(x,y1,y2,size,clr,opacity,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Здесь расчёт такой же, как описано для предыдущего метода.

Остальные методы рисования сглаженных и других примитивов:

//+------------------------------------------------------------------+
//| Рисует горизонтальный отрезок произвольной линии заданной толщины|
//| с использованием алгоритма сглаживания                           |
//| с предварительной фильтрацией                                    |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineThickHorizontalOnBG(const int   x1,                              // Координата X первой точки отрезка
                                             const int   x2,                              // Координата X второй точки отрезка
                                             const int   y,                               // Координата Y отрезка
                                             const int   size,                            // толщина линии
                                             const color clr,                             // Цвет
                                             const uchar opacity=255,                     // Непрозрачность
                                             const bool  redraw=false,                    // Флаг перерисовки чарта
                                             const uint  style=STYLE_SOLID,               // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                                             const ENUM_LINE_END end_style=LINE_END_ROUND)// Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
//--- Рассчитаем корректировку координат очерчивающего прямоугольника в зависимости от размера линии и типа её окончаний
   int correct_y=(int)::ceil((double)size/2.0);
   int correct_x=(end_style==LINE_END_BUTT ? 0 : correct_y);
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2)-correct_x;
   this.m_quad_y=y-correct_y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1+correct_x*2;
   this.m_quad_height=size;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawLineThickHorizontal(x1,x2,y,size,clr,opacity,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует ломаную линию с использованием                            |
//| алгоритма сглаживания AntiAliasing                               |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolylineAAOnBG(int         &array_x[],       // Массив координат X точек ломаной линии
                                    int         &array_y[],       // Массив координат Y точек ломаной линии
                                    const color clr,              // Цвет
                                    const uchar opacity=255,      // Непрозрачность
                                    const bool  redraw=false,     // Флаг перерисовки чарта
                                    const uint  style=UINT_MAX)   // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   this.m_quad_height=(max_y_value-min_y_value)+1;

//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolylineAA(array_x,array_y,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует ломаную линию с использованием алгоритма сглаживания Wu   |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolylineWuOnBG(int         &array_x[],       // Массив координат X точек ломаной линии
                                    int         &array_y[],       // Массив координат Y точек ломаной линии
                                    const color clr,              // Цвет
                                    const uchar opacity=255,      // Непрозрачность
                                    const bool  redraw=false,     // Флаг перерисовки чарта
                                    const uint  style=UINT_MAX)   // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   this.m_quad_height=(max_y_value-min_y_value)+1;

//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolylineWu(array_x,array_y,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует ломаную линию заданной толщины с использованием           |
//| двух алгоритмов сглаживания последовательно.                     |
//| Сначала на основе кривых Безье сглаживаются                      |
//| отдельные отрезки линии.                                         |
//| Затем для повышения качества отрисовки к построенной             |
//| из этих отрезков ломаной линии                                   |
//| применяется растровый алгоритм сглаживания                       |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolylineSmoothOnBG(const int    &array_x[],                    // Массив координат X точек ломаной линии
                                        const int    &array_y[],                    // Массив координат Y точек ломаной линии
                                        const int    size,                          // Толщина линии
                                        const color  clr,                           // Цвет
                                        const uchar  opacity=255,                   // Флаг перерисовки чарта
                                        const double tension=0.5,                   // Значение параметра сглаживания
                                        const double step=10,                       // Шаг аппроксимации
                                        const bool   redraw=false,                  // Флаг перерисовки чарта
                                        const ENUM_LINE_STYLE style=STYLE_SOLID,    // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                                        const ENUM_LINE_END   end_style=LINE_END_ROUND)// Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=0;
   this.m_quad_y=0;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=this.m_element.Width();
   this.m_quad_height=this.m_element.Height();
   
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }

//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;

//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolylineSmooth(array_x,array_y,size,clr,opacity,tension,step,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует ломаную линию заданной толщины с использованием           |
//| алгоритма сглаживания с предварительной фильтрацией              |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolylineThickOnBG(const int   &array_x[],                // Массив координат X точек ломаной линии
                                       const int   &array_y[],                // Массив координат Y точек ломаной линии
                                       const int   size,                      // Толщина линии
                                       const color clr,                       // Цвет
                                       const uchar opacity=255,               // Непрозрачность
                                       const bool  redraw=false,              // Флаг перерисовки чарта
                                       const uint  style=STYLE_SOLID,         // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                                       ENUM_LINE_END end_style=LINE_END_ROUND)// Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
//--- Рассчитаем корректировку координат очерчивающего прямоугольника в зависимости от размера линии
   int correct=int(::ceil((double)size/2.0))+1;
//--- Установим координаты очерчивающего прямоугольника
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x-correct;
   this.m_quad_y=y-correct;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1+correct*2;
   this.m_quad_height=(max_y_value-min_y_value)+1+correct*2;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolylineThick(array_x,array_y,size,clr,opacity,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует многоугольник с использованием                            |
//| алгоритма сглаживания AntiAliasing                               |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonAAOnBG(int         &array_x[],     // Массив координат X точек многоугольника
                                   int         &array_y[],     // Массив координат Y точек многоугольника
                                   const color clr,            // Цвет
                                   const uchar opacity=255,    // Непрозрачность
                                   const bool  redraw=false,   // Флаг перерисовки чарта
                                   const uint  style=UINT_MAX) // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   if(this.m_quad_width==0)
      this.m_quad_width=1;
   this.m_quad_height=(max_y_value-min_y_value)+1;
   if(this.m_quad_height==0)
      this.m_quad_height=1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolygonAA(array_x,array_y,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует многоугольник с использованием алгоритма сглаживания Wu   |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonWuOnBG(int         &array_x[],     // Массив координат X точек многоугольника
                                   int         &array_y[],     // Массив координат Y точек многоугольника
                                   const color clr,            // Цвет
                                   const uchar opacity=255,    // Непрозрачность
                                   const bool  redraw=false,   // Флаг перерисовки чарта
                                   const uint  style=UINT_MAX) // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   if(this.m_quad_width==0)
      this.m_quad_width=1;
   this.m_quad_height=(max_y_value-min_y_value)+1;
   if(this.m_quad_height==0)
      this.m_quad_height=1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolygonWu(array_x,array_y,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует  многоугольник заданной толщины с использованием          |
//| двух алгоритмов сглаживания последовательно.                     |
//| Сначала на основе кривых Безье сглаживаются отдельные отрезки.   |
//| Затем для повышения качества отрисовки к построенному            |
//| из этих отрезков многоугольнику применяется                      |
//| растровый алгоритм сглаживания.                                  |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonSmoothOnBG(int          &array_x[],                  // Массив координат X точек ломаной линии
                                       int          &array_y[],                  // Массив координат Y точек ломаной линии
                                       const int    size,                        // Толщина линии
                                       const color  clr,                         // Цвет
                                       const uchar  opacity=255,                 // Флаг перерисовки чарта
                                       const double tension=0.5,                 // Значение параметра сглаживания
                                       const double step=10,                     // Шаг аппроксимации
                                       const bool   redraw=false,                // Флаг перерисовки чарта
                                       const ENUM_LINE_STYLE style=STYLE_SOLID,  // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                                       const ENUM_LINE_END   end_style=LINE_END_ROUND)// Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=0;
   this.m_quad_y=0;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=this.m_element.Width();
   this.m_quad_height=this.m_element.Height();
   
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }

//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;

//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolygonSmooth(array_x,array_y,size,clr,opacity,tension,step,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует многоугольник заданной толщины с использованием           |
//| алгоритма сглаживания с предварительной фильтрацией              |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonThickOnBG(const int   &array_x[],                 // массив координат X точек многоугольника
                                      const int   &array_y[],                 // массив координат Y точек многоугольника
                                      const int   size,                       // толщина линии
                                      const color clr,                        // Цвет
                                      const uchar opacity=255,                // Непрозрачность
                                      const bool  redraw=false,               // Флаг перерисовки чарта
                                      const uint  style=STYLE_SOLID,          // стиль линии
                                      ENUM_LINE_END end_style=LINE_END_ROUND) // стиль концов линии
  {
//--- Рассчитаем корректировку координат очерчивающего прямоугольника в зависимости от размера линии
   int correct=int(::ceil((double)size/2.0))+1;
//--- Установим координаты очерчивающего прямоугольника
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x-correct;
   this.m_quad_y=y-correct;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1+correct*2;
   this.m_quad_height=(max_y_value-min_y_value)+1+correct*2;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawPolygonThick(array_x,array_y,size,clr,opacity,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует треугольник с использованием                              |
//| алгоритма сглаживания AntiAliasing                               |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawTriangleAAOnBG(const int   x1,               // Координата X первой вершины треугольника
                                    const int   y1,               // Координата Y первой вершины треугольника
                                    const int   x2,               // Координата X второй вершины треугольника
                                    const int   y2,               // Координата Y второй вершины треугольника
                                    const int   x3,               // Координата X третьей вершины треугольника
                                    const int   y3,               // Координата Y третьей вершины треугольника
                                    const color clr,              // Цвет
                                    const uchar opacity=255,      // Непрозрачность
                                    const bool  redraw=false,     // Флаг перерисовки чарта
                                    const uint  style=UINT_MAX)   // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(::fmin(x1,x2),x3);
   this.m_quad_y=::fmin(::fmin(y1,y2),y3);
   int max_x=::fmax(::fmax(x1,x2),x3);
   int max_y=::fmax(::fmax(y1,y2),y3);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=int(max_x-this.m_quad_x)+1;
   this.m_quad_height=int(max_y-this.m_quad_y)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawTriangleAA(x1,y1,x2,y2,x3,y3,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует треугольник с использованием алгоритма сглаживания Wu     |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawTriangleWuOnBG(const int   x1,               // Координата X первой вершины треугольника
                                    const int   y1,               // Координата Y первой вершины треугольника
                                    const int   x2,               // Координата X второй вершины треугольника
                                    const int   y2,               // Координата Y второй вершины треугольника
                                    const int   x3,               // Координата X третьей вершины треугольника
                                    const int   y3,               // Координата Y третьей вершины треугольника
                                    const color clr,              // Цвет
                                    const uchar opacity=255,      // Непрозрачность
                                    const bool  redraw=false,     // Флаг перерисовки чарта
                                    const uint  style=UINT_MAX)   // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(::fmin(x1,x2),x3);
   this.m_quad_y=::fmin(::fmin(y1,y2),y3);
   int max_x=::fmax(::fmax(x1,x2),x3);
   int max_y=::fmax(::fmax(y1,y2),y3);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=int(max_x-this.m_quad_x)+1;
   this.m_quad_height=int(max_y-this.m_quad_y)+1;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawTriangleWu(x1,y1,x2,y2,x3,y3,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует окружность с использованием                               |
//| алгоритма сглаживания AntiAliasing                               |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawCircleAAOnBG(const int    x,              // Координата X центра окружности
                                  const int    y,              // Координата Y центра окружности
                                  const double r,              // Радиус окружности
                                  const color  clr,            // Цвет
                                  const uchar  opacity=255,    // Непрозрачность
                                  const bool   redraw=false,   // Флаг перерисовки чарта
                                  const uint   style=UINT_MAX) // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   double rd=(r>0 ? r : 1);
   this.m_quad_x=x-rd;
   this.m_quad_y=y-rd;
   double x2=x+rd;
   double y2=y+rd;
   if(this.m_quad_x<0)
      this.m_quad_x=0;
   if(this.m_quad_y<0)
      this.m_quad_y=0;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=int(::ceil(x2-this.m_quad_x)+1);
   this.m_quad_height=int(::ceil(y2-this.m_quad_y)+1);
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawCircleAA(x,y,rd,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует окружность с использованием алгоритма сглаживания Wu      |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawCircleWuOnBG(const int    x,              // Координата X центра окружности
                                  const int    y,              // Координата Y центра окружности
                                  const double r,              // Радиус окружности
                                  const color  clr,            // Цвет
                                  const uchar  opacity=255,    // Непрозрачность
                                  const bool   redraw=false,   // Флаг перерисовки чарта
                                  const uint   style=UINT_MAX) // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   double rd=(r>0 ? r : 1);
   this.m_quad_x=x-rd;
   this.m_quad_y=y-rd;
   double x2=x+rd;
   double y2=y+rd;
   if(this.m_quad_x<0)
      this.m_quad_x=0;
   if(this.m_quad_y<0)
      this.m_quad_y=0;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=int(::ceil(x2-this.m_quad_x)+1);
   this.m_quad_height=int(::ceil(y2-this.m_quad_y)+1);
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawCircleWu(x,y,rd,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует эллипс по двум точкам с использованием                    |
//| алгоритма сглаживания AntiAliasing                               |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawEllipseAAOnBG(const double x1,               // Координата X первой точки, определяющей эллипс
                                   const double y1,               // Координата Y первой точки, определяющей эллипс
                                   const double x2,               // Координата X второй точки, определяющей эллипс
                                   const double y2,               // Координата Y второй точки, определяющей эллипс
                                   const color  clr,              // Цвет
                                   const uchar  opacity=255,      // Непрозрачность
                                   const bool   redraw=false,     // Флаг перерисовки чарта
                                   const uint   style=UINT_MAX)   // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2)-1;
   this.m_quad_y=::fmin(y1,y2)-1;
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=int(::ceil(::fabs(x2-x1)))+1;
   this.m_quad_height=int(::ceil(::fabs(y2-y1)))+1;
   
   if(this.m_quad_width<3)
      this.m_quad_width=3;
   if(this.m_quad_height<3)
      this.m_quad_height=3;
      
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawEllipseAA(x1,y1,x2,y2,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Рисует эллипс по двум точкам с использованием                    |
//| алгоритма сглаживания Wu                                         |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawEllipseWuOnBG(const int   x1,             // Координата X первой точки, определяющей эллипс
                                   const int   y1,             // Координата Y первой точки, определяющей эллипс
                                   const int   x2,             // Координата X второй точки, определяющей эллипс
                                   const int   y2,             // Координата Y второй точки, определяющей эллипс
                                   const color clr,            // Цвет
                                   const uchar opacity=255,    // Непрозрачность
                                   const bool  redraw=false,   // Флаг перерисовки чарта
                                   const uint  style=UINT_MAX) // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
//--- Установим координаты очерчивающего прямоугольника
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Установим ширину и высоту очерчивающего прямоугольника рисунка (это и будет размером сохраняемой области)
   this.m_quad_width=::fabs(x2-x1)+1;
   if(this.m_quad_width<3)
      this.m_quad_width=3;
   this.m_quad_height=::fabs(y2-y1)+1;
   if(this.m_quad_height<3)
      this.m_quad_height=3;
   
//--- Рассчитаем смещения координат для сохраняемой области в зависимости от точки привязки
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- Если массив пикселей не пустой - значит уже сохраняли фон под рисунком -
//--- восстановим фон, который ранее был сохранён (по прошлым координатам и смещениям)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- Если область фона с рассчитанными координатами и размерами под будущим рисунком успешно сохранена
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Нарисуем фигуру и обновим элемент
   this.m_element.DrawEllipseWu(x1,y1,x2,y2,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

Здесь у всех методов алгоритмы расчёта сохраняемой области фона примерно идентичны алгоритмам расчёта в вышерассмотренных методах.

Хочется уточнить, что в методах рисования эллипсов (DrawEllipseAAOnBG и DrawEllipseWuOnBG) если размер прямоугольника, внутри которого рисуется эллипс, меньше трёх пикселей, то фигура не рисуется. Поэтому здесь в расчётах стоит проверка на размер менее трёх пикселей. Что это — моё непонимание как рисуется эллипс, или так заложено в методы класса CCanvas, я пока не понял. Надеюсь, в дальнейшем разберусь.

Все нужные на сегодня классы объектов-кадров анимаций созданы.

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

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

Класс анимаций формы

В папке \MQL5\Include\DoEasy\Objects\Graph\Animations\ создадим новый файл Animations.mqh класса CAnimations.

К файлу класса должны быть подключены только что созданные файлы классов-наследников базового объекта-кадра анимации, а сам класс должен быть наследником базового объекта стандартной библиотеки CObject:

//+------------------------------------------------------------------+
//|                                                   Animations.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property strict    // Нужно для mql4
//+------------------------------------------------------------------+
//| Включаемые файлы                                                 |
//+------------------------------------------------------------------+
#include "FrameText.mqh"
#include "FrameQuad.mqh"
//+------------------------------------------------------------------+
//| Класс копировщика пикселей                                       |
//+------------------------------------------------------------------+
class CAnimations : public CObject
  {
  }

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

//+------------------------------------------------------------------+
//| Класс копировщика пикселей                                       |
//+------------------------------------------------------------------+
class CAnimations : public CObject
  {
private:
   CGCnvElement     *m_element;                             // Указатель на графический элемент
   CArrayObj         m_list_frames_text;                    // Список текстовых кадров анимаций
   CArrayObj         m_list_frames_quad;                    // Список прямоугольных кадров анимаций

//--- Возвращает флаг присутствия в списке объекта-кадра с указанным идентификатором
   bool              IsPresentFrame(const ENUM_ANIMATION_FRAME_TYPE frame_type,const int id);
//--- Возвращает или создаёт новый объект-кадр анимации
   CFrame           *GetOrCreateFrame(const string soutce,const int id,const ENUM_ANIMATION_FRAME_TYPE frame_type,const bool create_new);

public:

Все методы рассмотрим далее.

В публичной секции класса объявим методы для создания и работы с объектами в списках и методы рисования примитивов с сохранением и восстановлением фона:

public:
                     CAnimations(CGCnvElement *element);
                     CAnimations(){;}

//--- Создаёт новый (1) прямоугольный, (2) текстовый объект-кадр анимации
   CFrame           *CreateNewFrameText(const int id);
   CFrame           *CreateNewFrameQuad(const int id);
//--- Возвращает объект-кадр анимации по идентификатору
   CFrame           *GetFrame(const ENUM_ANIMATION_FRAME_TYPE frame_type,const int id);
//--- Возвращает список (1) текстовых, (2) прямоугольных кадров анимаций
   CArrayObj        *GetListFramesText(void)                { return &this.m_list_frames_text;  }
   CArrayObj        *GetListFramesQuad(void)                { return &this.m_list_frames_quad;  }

//+------------------------------------------------------------------+
//| Методы рисования с сохранением и восстановлением фона            |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Выводит текст на фон                                             |
//+------------------------------------------------------------------+
   bool              TextOnBG(const int id,
                              const string text,
                              const int x,
                              const int y,
                              const ENUM_TEXT_ANCHOR anchor,
                              const color clr,
                              const uchar opacity,
                              const bool create_new=true,
                              const bool redraw=false);
//+------------------------------------------------------------------+
//| Методы рисования примитивов без сглаживания                      |
//+------------------------------------------------------------------+
//--- Устанавливает цвет точки с указанными координатами
   bool              SetPixelOnBG(const int id,const int x,const int y,const color clr,const uchar opacity=255,const bool create_new=true,const bool redraw=false);
                       
//--- Рисует отрезок вертикальной линии
   bool              DrawLineVerticalOnBG(const int id,                 // Идентификатор кадра
                              const int   x,                            // Координата X отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует отрезок горизонтальной линии
   bool              DrawLineHorizontalOnBG(const int id,               // Идентификатор кадра
                              const int   x1,                           // Координата X первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y,                            // Координата Y отрезка
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует отрезок произвольной линии
   bool              DrawLineOnBG(const int id,                         // Идентификатор кадра
                              const int   x1,                           // Координата X первой точки отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует ломаную линию
   bool              DrawPolylineOnBG(const int id,                     // Идентификатор кадра
                              int         &array_x[],                   // Массив координат X точек ломаной линии
                              int         &array_y[],                   // Массив координат Y точек ломаной линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует многоугольник
   bool              DrawPolygonOnBG(const int id,                      // Идентификатор кадра
                              int         &array_x[],                   // Массив координат X точек многоугольника
                              int         &array_y[],                   // Массив координат Y точек многоугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует прямоугольник по двум точкам
   bool              DrawRectangleOnBG(const int id,                    // Идентификатор кадра
                              const int   x1,                           // Координата X первой точки, определяющей прямоугольник
                              const int   y1,                           // Координата Y первой точки, определяющей прямоугольник
                              const int   x2,                           // Координата X второй точки, определяющей прямоугольник
                              const int   y2,                           // Координата Y второй точки, определяющей прямоугольник
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует окружность
   bool              DrawCircleOnBG(const int id,                       // Идентификатор кадра
                              const int   x,                            // Координата X центра окружности
                              const int   y,                            // Координата Y центра окружности
                              const int   r,                            // Радиус окружности
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует треугольник
   bool              DrawTriangleOnBG(const int id,                     // Идентификатор кадра
                              const int   x1,                           // Координата X первой вершины треугольника
                              const int   y1,                           // Координата Y первой вершины треугольника
                              const int   x2,                           // Координата X второй вершины треугольника
                              const int   y2,                           // Координата Y второй вершины треугольника
                              const int   x3,                           // Координата X третьей вершины треугольника
                              const int   y3,                           // Координата Y третьей вершины треугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует эллипс по двум точкам
   bool              DrawEllipseOnBG(const int id,                      // Идентификатор кадра
                              const int   x1,                           // Координата X первой точки, определяющей эллипс
                              const int   y1,                           // Координата Y первой точки, определяющей эллипс
                              const int   x2,                           // Координата X второй точки, определяющей эллипс
                              const int   y2,                           // Координата Y второй точки, определяющей эллипс
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует дугу эллипса, вписанного в прямоугольник с углами в (x1,y1) и (x2,y2).
//--- Границы дуги отсекаются линиями из центра эллипса, идущими к двум точкам с координатами (x3,y3) и (x4,y4)
   bool              DrawArcOnBG(const int id,                          // Идентификатор кадра
                              const int   x1,                           // Координата X левого верхнего угла, определяющего прямоугольник
                              const int   y1,                           // Координата Y левого верхнего угла, определяющего прямоугольник
                              const int   x2,                           // Координата X правого нижнего угла, определяющего прямоугольник
                              const int   y2,                           // Координата Y правого нижнего угла, определяющего прямоугольник
                              const int   x3,                           // Координата X первой точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                              const int   y3,                           // Координата Y первой точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                              const int   x4,                           // Координата X второй точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                              const int   y4,                           // Координата Y второй точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует закрашенный сектор эллипса, вписанного в прямоугольник с углами в (x1,y1) и (x2,y2).
//--- Границы сектора отсекаются линиями из центра эллипса, идущими к двум точкам с координатами (x3,y3) и (x4,y4)
   bool              DrawPieOnBG(const int id,                          // Идентификатор кадра
                              const int   x1,                           // координата X верхнего левого угла прямоугольника
                              const int   y1,                           // координата Y верхнего левого угла прямоугольника
                              const int   x2,                           // координата X нижнего правого угла прямоугольника
                              const int   y2,                           // координата Y нижнего правого угла прямоугольника
                              const int   x3,                           // координата X первой точки для нахождения границы дуги
                              const int   y3,                           // координата Y первой точки для нахождения границы дуги
                              const int   x4,                           // координата X второй точки для нахождения границы дуги
                              const int   y4,                           // координата Y второй точки для нахождения границы дуги
                              const color clr,                          // Цвет
                              const color fill_clr,                     // Цвет заливки
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//+------------------------------------------------------------------+
//| Методы рисования закрашенных примитивов без сглаживания          |
//+------------------------------------------------------------------+
//--- Закрашивает область
   bool              FillOnBG(const int   id,                           // Идентификатор кадра
                              const int   x,                            // Координата X точки начала закрашивания
                              const int   y,                            // Координата Y точки начала закрашивания
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const uint  threshould=0,                 // Порог
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует закрашенный прямоугольник
   bool              DrawRectangleFillOnBG(const int id,                // Идентификатор кадра
                              const int   x1,                           // Координата X первой точки, определяющей прямоугольник
                              const int   y1,                           // Координата Y первой точки, определяющей прямоугольник
                              const int   x2,                           // Координата X второй точки, определяющей прямоугольник
                              const int   y2,                           // Координата Y второй точки, определяющей прямоугольник
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта

//--- Рисует закрашенный круг
   bool              DrawCircleFillOnBG(const int id,                   // Идентификатор кадра
                              const int   x,                            // Координата X центра круга
                              const int   y,                            // Координата Y центра круга
                              const int   r,                            // Радиус круга
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует закрашенный треугольник
   bool              DrawTriangleFillOnBG(const int id,                 // Идентификатор кадра
                              const int   x1,                           // Координата X первой вершины треугольника
                              const int   y1,                           // Координата Y первой вершины треугольника
                              const int   x2,                           // Координата X второй вершины треугольника
                              const int   y2,                           // Координата Y второй вершины треугольника
                              const int   x3,                           // Координата X третьей вершины треугольника
                              const int   y3,                           // Координата Y третьей вершины треугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует закрашенный многоугольник
   bool              DrawPolygonFillOnBG(const int id,                  // Идентификатор кадра
                              int         &array_x[],                   // Массив, содержащий координаты X точек многоугольника
                              int         &array_y[],                   // Массив, содержащий координаты Y точек многоугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//--- Рисует закрашенный эллипс, вписанный в прямоугольник с заданными координатами
   bool              DrawEllipseFillOnBG(const int id,                  // Идентификатор кадра
                              const int   x1,                           // Координата X левого верхнего угла, определяющего прямоугольник
                              const int   y1,                           // Координата Y левого верхнего угла, определяющего прямоугольник
                              const int   x2,                           // Координата X правого нижнего угла, определяющего прямоугольник
                              const int   y2,                           // Координата Y правого нижнего угла, определяющего прямоугольник
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false);                // Флаг перерисовки чарта
                       
//+------------------------------------------------------------------+
//| Методы рисования примитивов с использованием сглаживания         |
//+------------------------------------------------------------------+
//--- Рисует точку с использованием алгоритма сглаживания AntiAliasing
   bool              SetPixelAAOnBG(const int id,                       // Идентификатор кадра
                              const double x,                           // Координата X точки
                              const double y,                           // Координата Y точки
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const bool   create_new=true,             // Флаг создания нового объекта
                              const bool   redraw=false);               // Флаг перерисовки чарта
                       
//--- Рисует отрезок произвольной линии с использованием алгоритма сглаживания AntiAliasing
   bool              DrawLineAAOnBG(const int id,                       // Идентификатор кадра
                              const int   x1,                           // Координата X первой точки отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует отрезок произвольной линии с использованием алгоритма сглаживания Wu
   bool              DrawLineWuOnBG(const int id,                       // Идентификатор кадра
                              const int   x1,                           // Координата X первой точки отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует отрезок произвольной линии заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
   bool              DrawLineThickOnBG(const int id,                    // Идентификатор кадра
                              const int   x1,                           // Координата X первой точки отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const int   size,                         // Толщина линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=STYLE_SOLID,            // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              ENUM_LINE_END end_style=LINE_END_ROUND);  // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
 
//--- Рисует вертикальный отрезок произвольной линии заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
   bool              DrawLineThickVerticalOnBG(const int id,            // Идентификатор кадра
                              const int   x,                            // Координата X отрезка
                              const int   y1,                           // Координата Y первой точки отрезка
                              const int   y2,                           // Координата Y второй точки отрезка
                              const int   size,                         // толщина линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=STYLE_SOLID,            // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              const ENUM_LINE_END end_style=LINE_END_ROUND); // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
                       
//--- Рисует горизонтальный отрезок произвольной линии заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
   bool              DrawLineThickHorizontalOnBG(const int id,          // Идентификатор кадра
                              const int   x1,                           // Координата X первой точки отрезка
                              const int   x2,                           // Координата X второй точки отрезка
                              const int   y,                            // Координата Y отрезка
                              const int   size,                         // толщина линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=STYLE_SOLID,            // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              const ENUM_LINE_END end_style=LINE_END_ROUND); // Стиль концов линии — одно из значений перечисления ENUM_LINE_END

//--- Рисует ломаную линию с использованием алгоритма сглаживания AntiAliasing
   bool              DrawPolylineAAOnBG(const int id,                   // Идентификатор кадра
                              int         &array_x[],                   // Массив координат X точек ломаной линии
                              int         &array_y[],                   // Массив координат Y точек ломаной линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует ломаную линию с использованием алгоритма сглаживания Wu
   bool              DrawPolylineWuOnBG(const int id,                   // Идентификатор кадра
                              int         &array_x[],                   // Массив координат X точек ломаной линии
                              int         &array_y[],                   // Массив координат Y точек ломаной линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует ломаную линию заданной толщины с использованием двух алгоритмов сглаживания последовательно.
//--- Сначала на основе кривых Безье сглаживаются отдельные отрезки линии.
//--- Затем для повышения качества отрисовки к построенной из этих отрезков ломаной линии применяется растровый алгоритм сглаживания
   bool              DrawPolylineSmoothOnBG(const int id,               // Идентификатор кадра
                              const int    &array_x[],                  // Массив координат X точек ломаной линии
                              const int    &array_y[],                  // Массив координат Y точек ломаной линии
                              const int    size,                        // Толщина линии
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const double tension=0.5,                 // Значение параметра сглаживания
                              const double step=10,                     // Шаг аппроксимации
                              const bool   create_new=true,             // Флаг создания нового объекта
                              const bool   redraw=false,                // Флаг перерисовки чарта
                              const ENUM_LINE_STYLE style=STYLE_SOLID,  // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              const ENUM_LINE_END end_style=LINE_END_ROUND);// Стиль концов линии — одно из значений перечисления ENUM_LINE_END
                       
//--- Рисует ломаную линию заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
   bool              DrawPolylineThickOnBG(const int id,                // Идентификатор кадра
                              const int     &array_x[],                 // Массив координат X точек ломаной линии
                              const int     &array_y[],                 // Массив координат Y точек ломаной линии
                              const int     size,                       // Толщина линии
                              const color   clr,                        // Цвет
                              const uchar   opacity=255,                // Непрозрачность
                              const bool    create_new=true,            // Флаг создания нового объекта
                              const bool    redraw=false,               // Флаг перерисовки чарта
                              const uint    style=STYLE_SOLID,          // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              ENUM_LINE_END end_style=LINE_END_ROUND);  // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
                       
//--- Рисует многоугольник с использованием алгоритма сглаживания AntiAliasing
   bool              DrawPolygonAAOnBG(const int id,                    // Идентификатор кадра
                              int         &array_x[],                   // Массив координат X точек многоугольника
                              int         &array_y[],                   // Массив координат Y точек многоугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует многоугольник с использованием алгоритма сглаживания Wu
   bool              DrawPolygonWuOnBG(const int id,                    // Идентификатор кадра
                              int         &array_x[],                   // Массив координат X точек многоугольника
                              int         &array_y[],                   // Массив координат Y точек многоугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует  многоугольник заданной толщины с использованием двух алгоритмов сглаживания последовательно.
//--- Сначала на основе кривых Безье сглаживаются отдельные отрезки.
//--- Затем для повышения качества отрисовки к построенному из этих отрезков многоугольнику применяется растровый алгоритм сглаживания. 
   bool              DrawPolygonSmoothOnBG(const int id,                // Идентификатор кадра
                              int          &array_x[],                  // Массив координат X точек ломаной линии
                              int          &array_y[],                  // Массив координат Y точек ломаной линии
                              const int    size,                        // Толщина линии
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const double tension=0.5,                 // Значение параметра сглаживания
                              const double step=10,                     // Шаг аппроксимации
                              const bool   create_new=true,             // Флаг создания нового объекта
                              const bool   redraw=false,                // Флаг перерисовки чарта
                              const ENUM_LINE_STYLE style=STYLE_SOLID,  // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                              const ENUM_LINE_END end_style=LINE_END_ROUND);// Стиль концов линии — одно из значений перечисления ENUM_LINE_END
                       
//--- Рисует многоугольник заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
   bool              DrawPolygonThickOnBG(const int id,                 // Идентификатор кадра
                              const int   &array_x[],                   // массив координат X точек многоугольника
                              const int   &array_y[],                   // массив координат Y точек многоугольника
                              const int   size,                         // толщина линии
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=STYLE_SOLID,            // стиль линии
                              ENUM_LINE_END end_style=LINE_END_ROUND);  // стиль концов линии
                       
//--- Рисует треугольник с использованием алгоритма сглаживания AntiAliasing
   bool              DrawTriangleAAOnBG(const int id,                   // Идентификатор кадра
                              const int   x1,                           // Координата X первой вершины треугольника
                              const int   y1,                           // Координата Y первой вершины треугольника
                              const int   x2,                           // Координата X второй вершины треугольника
                              const int   y2,                           // Координата Y второй вершины треугольника
                              const int   x3,                           // Координата X третьей вершины треугольника
                              const int   y3,                           // Координата Y третьей вершины треугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует треугольник с использованием алгоритма сглаживания Wu
   bool              DrawTriangleWuOnBG(const int id,                   // Идентификатор кадра
                              const int   x1,                           // Координата X первой вершины треугольника
                              const int   y1,                           // Координата Y первой вершины треугольника
                              const int   x2,                           // Координата X второй вершины треугольника
                              const int   y2,                           // Координата Y второй вершины треугольника
                              const int   x3,                           // Координата X третьей вершины треугольника
                              const int   y3,                           // Координата Y третьей вершины треугольника
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует окружность с использованием алгоритма сглаживания AntiAliasing
   bool              DrawCircleAAOnBG(const int id,                     // Идентификатор кадра
                              const int    x,                           // Координата X центра окружности
                              const int    y,                           // Координата Y центра окружности
                              const double r,                           // Радиус окружности
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const bool   create_new=true,             // Флаг создания нового объекта
                              const bool   redraw=false,                // Флаг перерисовки чарта
                              const uint   style=UINT_MAX);             // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует окружность с использованием алгоритма сглаживания Wu
   bool              DrawCircleWuOnBG(const int id,                     // Идентификатор кадра
                              const int    x,                           // Координата X центра окружности
                              const int    y,                           // Координата Y центра окружности
                              const double r,                           // Радиус окружности
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const bool   create_new=true,             // Флаг создания нового объекта
                              const bool   redraw=false,                // Флаг перерисовки чарта
                              const uint   style=UINT_MAX);             // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует эллипс по двум точкам с использованием алгоритма сглаживания AntiAliasing
   bool              DrawEllipseAAOnBG(const int id,                    // Идентификатор кадра
                              const double x1,                          // Координата X первой точки, определяющей эллипс
                              const double y1,                          // Координата Y первой точки, определяющей эллипс
                              const double x2,                          // Координата X второй точки, определяющей эллипс
                              const double y2,                          // Координата Y второй точки, определяющей эллипс
                              const color  clr,                         // Цвет
                              const uchar  opacity=255,                 // Непрозрачность
                              const bool   create_new=true,             // Флаг создания нового объекта
                              const bool   redraw=false,                // Флаг перерисовки чарта
                              const uint   style=UINT_MAX);             // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                       
//--- Рисует эллипс по двум точкам с использованием алгоритма сглаживания Wu
   bool              DrawEllipseWuOnBG(const int id,                    // Идентификатор кадра
                              const int   x1,                           // Координата X первой точки, определяющей эллипс
                              const int   y1,                           // Координата Y первой точки, определяющей эллипс
                              const int   x2,                           // Координата X второй точки, определяющей эллипс
                              const int   y2,                           // Координата Y второй точки, определяющей эллипс
                              const color clr,                          // Цвет
                              const uchar opacity=255,                  // Непрозрачность
                              const bool  create_new=true,              // Флаг создания нового объекта
                              const bool  redraw=false,                 // Флаг перерисовки чарта
                              const uint  style=UINT_MAX);              // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  };
//+------------------------------------------------------------------+


Рассмотрим реализацию объявленных методов.

Параметрический конструктор:

//+------------------------------------------------------------------+
//| Параметрический конструктор                                      |
//+------------------------------------------------------------------+
CAnimations::CAnimations(CGCnvElement *element)
  {
   this.m_element=element;
  }
//+------------------------------------------------------------------+

Здесь устанавливаем указателю m_element переданное в аргументах значение указателя на объект-графический элемент.

Метод, возвращающий указатель на объект-кадр анимации по типу и идентификатору:

//+------------------------------------------------------------------+
//| Возвращает объект-кадр анимации по типу и идентификатору         |
//+------------------------------------------------------------------+
CFrame *CAnimations::GetFrame(const ENUM_ANIMATION_FRAME_TYPE frame_type,const int id)
  {
//--- Объявляем указатель на объект-кадр анимации
   CFrame *frame=NULL;
//--- В зависимости от типа нужного объекта получаем их количество в соответствующем списке
   int total=
     (
      frame_type==ANIMATION_FRAME_TYPE_TEXT ? this.m_list_frames_text.Total() : 
      frame_type==ANIMATION_FRAME_TYPE_QUAD ? this.m_list_frames_quad.Total() : 0
     );
//--- В цикле ...
   for(int i=0;i<total;i++)
     {
      //--- ... по списку, соответствующему типу кадра анимации получаем очередной объект
      switch(frame_type)
        {
         case ANIMATION_FRAME_TYPE_TEXT : frame=this.m_list_frames_text.At(i); break;
         case ANIMATION_FRAME_TYPE_QUAD : frame=this.m_list_frames_quad.At(i); break;
         default: break;
        }
      //--- если указатель получить не удалось - идём к следующему
      if(frame==NULL)
         continue;
      //--- Если идентификатор объекта соответствует искомому -
      //--- возвращаем указатель на найденный объект
      if(frame.ID()==id)
         return frame;
     }
//--- Ничего не нашли - возвращаем NULL
   return NULL;
  }
//+------------------------------------------------------------------+

Логика метода полностью расписана в комментариях к коду и в дополнительных пояснениях не нуждается.

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

//+------------------------------------------------------------------+
//| Возвращает флаг присутствия в списке объекта-кадра анимации      |
//| с указанным типом и идентификатором                              |
//+------------------------------------------------------------------+
bool CAnimations::IsPresentFrame(const ENUM_ANIMATION_FRAME_TYPE frame_type,const int id)
  {
   return(this.GetFrame(frame_type,id)!=NULL);
  }
//+------------------------------------------------------------------+

Метод возвращает bool-результат вызова вышерассмотренного метода GetFrame(). Если метод GetFrame() вернул результат не NULL (т.е., искомый объект есть в списке), то метод вернёт true, иначе — false.

Метод, создающий новый текстовый объект-кадр анимации:

//+------------------------------------------------------------------+
//| Создаёт новый текстовый объект-кадр анимации                     |
//+------------------------------------------------------------------+
CFrame *CAnimations::CreateNewFrameText(const int id)
  {
//--- Если объект с таким идентификатором уже есть - сообщаем об этом в журнал и возвращаем NULL
   if(this.IsPresentFrame(ANIMATION_FRAME_TYPE_TEXT,id))
     {
      ::Print(DFUN,CMessage::Text(MSG_FORM_OBJECT_FRAME_ALREADY_IN_LIST),(string)id);
      return NULL;
     }
//--- Создаём новый текстовый объект-кадр анимации с указанным идентификатором
   CFrame *frame=new CFrameText(id,this.m_element);
//--- Если объект создать не удалось - сообщаем об этом и возвращаем NULL
   if(frame==NULL)
     {
      ::Print(DFUN,CMessage::Text(MSG_FORM_OBJECT_ERR_FAILED_CREATE_FRAME));
      return NULL;
     }
//--- Если успешно созданный объект не удалось добавить в список - сообщаем об этом, удаляем объект и возвращаем NULL
   if(!this.m_list_frames_text.Add(frame))
     {
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST)," ID: ",id);
      delete frame;
      return NULL;
     }
//--- Возвращаем указатель на вновь созданный объект
   return frame;
  }
//+------------------------------------------------------------------+

Логика метода полностью расписана в комментариях к коду.

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

//+------------------------------------------------------------------+
//| Создаёт новый прямоугольный объект-кадр анимации                 |
//+------------------------------------------------------------------+
CFrame *CAnimations::CreateNewFrameQuad(const int id)
  {
//--- Если объект с таким идентификатором уже есть - сообщаем об этом в журнал и возвращаем NULL
   if(this.IsPresentFrame(ANIMATION_FRAME_TYPE_QUAD,id))
     {
      ::Print(DFUN,CMessage::Text(MSG_FORM_OBJECT_FRAME_ALREADY_IN_LIST),(string)id);
      return NULL;
     }
//--- Создаём новый прямоугольный объект-кадр анимации с указанным идентификатором
   CFrame *frame=new CFrameQuad(id,this.m_element);
//--- Если объект создать не удалось - сообщаем об этом и возвращаем NULL
   if(frame==NULL)
     {
      ::Print(DFUN,CMessage::Text(MSG_FORM_OBJECT_ERR_FAILED_CREATE_FRAME));
      return NULL;
     }
//--- Если успешно созданный объект не удалось добавить в список - сообщаем об этом, удаляем объект и возвращаем NULL
   if(!this.m_list_frames_quad.Add(frame))
     {
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST)," ID: ",id);
      delete frame;
      return NULL;
     }
//--- Возвращаем указатель на вновь созданный объект
   return frame;
  }
//+------------------------------------------------------------------+

Метод идентичен вышерассмотренному, так же полностью прокомментирован и в дополнительных пояснениях не нуждается.

Метод, возвращающий указатель или создающий новый объект-кадр анимации:

//+------------------------------------------------------------------+
//| Возвращает или создаёт новый объект-кадр анимации                |
//+------------------------------------------------------------------+
CFrame *CAnimations::GetOrCreateFrame(const string source,const int id,const ENUM_ANIMATION_FRAME_TYPE frame_type,const bool create_new)
  {
   //--- Объявляем нулевые указатели на объекты
   CFrameQuad *frame_q=NULL;
   CFrameText *frame_t=NULL;
   //--- В зависимости от типа требуемого объекта
   switch(frame_type)
     {
      //--- Если это текстовый анимационный кадр
      case ANIMATION_FRAME_TYPE_TEXT :
        //--- получим указатель на объект с указанным идентификатором
        frame_t=this.GetFrame(ANIMATION_FRAME_TYPE_TEXT,id);
        //--- Если указатель получен - вернём его
        if(frame_t!=NULL)
           return frame_t;
        //--- Если не установлен флаг создания нового объекта - сообщим об ошибке и вернём NULL
        if(!create_new)
          {
           ::Print(source,CMessage::Text(MSG_FORM_OBJECT_FRAME_NOT_EXIST_LIST),(string)id);
           return NULL;
          }
        //--- Вернём результат создания нового объекта-кадра текстовой анимации (указатель на созданный объект)
        return this.CreateNewFrameText(id);
      
      //--- Если это прямоугольный анимационный кадр
      case ANIMATION_FRAME_TYPE_QUAD :
        //--- получим указатель на объект с указанным идентификатором
        frame_q=this.GetFrame(ANIMATION_FRAME_TYPE_QUAD,id);
        //--- Если указатель получен - вернём его
        if(frame_q!=NULL)
           return frame_q;
        //--- Если не установлен флаг создания нового объекта - сообщим об ошибке и вернём NULL
        if(!create_new)
          {
           ::Print(source,CMessage::Text(MSG_FORM_OBJECT_FRAME_NOT_EXIST_LIST),(string)id);
           return NULL;
          }
        //--- Вернём результат создания нового объекта-прямоугольного кадра анимации (указатель на созданный объект)
        return this.CreateNewFrameQuad(id);
      //--- Остальные случаи - возвращаем NULL
      default:
        return NULL;
     }
  }
//+------------------------------------------------------------------+

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

Методы работы с объектами-кадрами анимаций.

Метод, выводящий текст на фон с сохранением и восстановлением фона:

//+------------------------------------------------------------------+
//| Выводит текст на фон с сохранением и восстановлением фона        |
//+------------------------------------------------------------------+
bool CAnimations::TextOnBG(const int id,
                           const string text,
                           const int x,
                           const int y,
                           const ENUM_TEXT_ANCHOR anchor,
                           const color clr,
                           const uchar opacity,
                           const bool create_new=true,
                           const bool redraw=false)
  {
   CFrameText *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_TEXT,create_new);
   if(frame==NULL)
      return false;
   return frame.TextOnBG(text,x,y,anchor,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+

В метод передаются идентификатор объекта, параметры выводимого текста (сам текст, координаты X и Y, точка привязки, цвет и непрозрачность), флаг необхоимости создать новый объект с указанным идентификатором в случае, если объекта с таким идентификатором нет в списке, и флаг перерисовки чарта.
Далее получаем указатель на требуемый объект (или создаём объект при его отсутствии). Если указатель получить не удалось, возвращаем false.
Если указатель получен, возвращаем результат работы метода TextOnBG() полученного объекта-кадра текстовой анимации.

Метод, устанавливающий цвет точки с указанными координатами:

//+------------------------------------------------------------------+
//| Устанавливает цвет точки с указанными координатами               |
//+------------------------------------------------------------------+
bool CAnimations::SetPixelOnBG(const int id,const int x,const int y,const color clr,const uchar opacity=255,const bool create_new=true,const bool redraw=false)
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.SetPixelOnBG(x,y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+

Логика метода идентична логике вышерассмотренного метода. В метод передаются идентификатор объекта, координаты X и Y рисуемой фигуры, её цвет и непрозрачность, флаг необходимости создать новый объект с указанным идентификатором в случае, если объекта с таким идентификатором нет в списке, и флаг перерисовки чарта.
Далее получаем указатель на требуемый объект (или создаём объект при его отсутствии). Если указатель получить не удалось, возвращаем false.
Если указатель получен, возвращаем результат работы метода SetPixelOnBG() полученного объекта-прямоугольного кадра анимации.

Остальные методы рисования примитивов.

Логика остальных методов рисования фигур идентична логике вышерассмотренных методов. Просто посмотрим их листинг:

//+------------------------------------------------------------------+
//| Рисует отрезок вертикальной линии                                |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineVerticalOnBG(const int id,                 // Идентификатор кадра
                           const int   x,                            // Координата X отрезка
                           const int   y1,                           // Координата Y первой точки отрезка
                           const int   y2,                           // Координата Y второй точки отрезка
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineVerticalOnBG(x,y1,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует отрезок горизонтальной линии                              |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineHorizontalOnBG(const int id,               // Идентификатор кадра
                           const int   x1,                           // Координата X первой точки отрезка
                           const int   x2,                           // Координата X второй точки отрезка
                           const int   y,                            // Координата Y отрезка
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineHorizontalOnBG(x1,x2,y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует отрезок произвольной линии                                |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineOnBG(const int id,                         // Идентификатор кадра
                           const int   x1,                           // Координата X первой точки отрезка
                           const int   y1,                           // Координата Y первой точки отрезка
                           const int   x2,                           // Координата X второй точки отрезка
                           const int   y2,                           // Координата Y второй точки отрезка
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineOnBG(x1,y1,x2,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует ломаную линию                                             |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolylineOnBG(const int id,                     // Идентификатор кадра
                           int         &array_x[],                   // Массив координат X точек ломаной линии
                           int         &array_y[],                   // Массив координат Y точек ломаной линии
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolylineOnBG(array_x,array_y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует многоугольник                                             |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolygonOnBG(const int id,                      // Идентификатор кадра
                           int         &array_x[],                   // Массив координат X точек многоугольника
                           int         &array_y[],                   // Массив координат Y точек многоугольника
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonOnBG(array_x,array_y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует прямоугольник по двум точкам                              |
//+------------------------------------------------------------------+
bool CAnimations::DrawRectangleOnBG(const int id,                    // Идентификатор кадра
                           const int   x1,                           // Координата X первой точки, определяющей прямоугольник
                           const int   y1,                           // Координата Y первой точки, определяющей прямоугольник
                           const int   x2,                           // Координата X второй точки, определяющей прямоугольник
                           const int   y2,                           // Координата Y второй точки, определяющей прямоугольник
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawRectangleOnBG(x1,y1,x2,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует окружность                                                |
//+------------------------------------------------------------------+
bool CAnimations::DrawCircleOnBG(const int id,                       // Идентификатор кадра
                           const int   x,                            // Координата X центра окружности
                           const int   y,                            // Координата Y центра окружности
                           const int   r,                            // Радиус окружности
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawCircleOnBG(x,y,r,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует треугольник                                               |
//+------------------------------------------------------------------+
bool CAnimations::DrawTriangleOnBG(const int id,                     // Идентификатор кадра
                           const int   x1,                           // Координата X первой вершины треугольника
                           const int   y1,                           // Координата Y первой вершины треугольника
                           const int   x2,                           // Координата X второй вершины треугольника
                           const int   y2,                           // Координата Y второй вершины треугольника
                           const int   x3,                           // Координата X третьей вершины треугольника
                           const int   y3,                           // Координата Y третьей вершины треугольника
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawTriangleOnBG(x1,y1,x2,y2,x3,y3,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует эллипс по двум точкам                                     |
//+------------------------------------------------------------------+
bool CAnimations::DrawEllipseOnBG(const int id,                      // Идентификатор кадра
                           const int   x1,                           // Координата X первой точки, определяющей эллипс
                           const int   y1,                           // Координата Y первой точки, определяющей эллипс
                           const int   x2,                           // Координата X второй точки, определяющей эллипс
                           const int   y2,                           // Координата Y второй точки, определяющей эллипс
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawEllipseOnBG(x1,y1,x2,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует дугу эллипса, вписанного в прямоугольник                  |
//| с углами в (x1,y1) и (x2,y2).                                    |
//| Границы дуги отсекаются линиями из центра эллипса,               |
//| идущими к двум точкам с координатами (x3,y3) и (x4,y4)           |
//+------------------------------------------------------------------+
bool CAnimations::DrawArcOnBG(const int id,                          // Идентификатор кадра
                           const int   x1,                           // Координата X левого верхнего угла, определяющего прямоугольник
                           const int   y1,                           // Координата Y левого верхнего угла, определяющего прямоугольник
                           const int   x2,                           // Координата X правого нижнего угла, определяющего прямоугольник
                           const int   y2,                           // Координата Y правого нижнего угла, определяющего прямоугольник
                           const int   x3,                           // Координата X первой точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                           const int   y3,                           // Координата Y первой точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                           const int   x4,                           // Координата X второй точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                           const int   y4,                           // Координата Y второй точки, к которой проведена линия из центра прямоугольника для получения границы дуги
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawArcOnBG(x1,y1,x2,y2,x3,y3,x4,y4,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный сектор эллипса, вписанного в прямоугольник    |
//| с углами в (x1,y1) и (x2,y2).                                    |
//| Границы сектора отсекаются линиями из центра эллипса,            |
//| идущими к двум точкам с координатами (x3,y3) и (x4,y4)           |
//+------------------------------------------------------------------+
bool CAnimations::DrawPieOnBG(const int id,                          // Идентификатор кадра
                           const int   x1,                           // координата X верхнего левого угла прямоугольника
                           const int   y1,                           // координата Y верхнего левого угла прямоугольника
                           const int   x2,                           // координата X нижнего правого угла прямоугольника
                           const int   y2,                           // координата Y нижнего правого угла прямоугольника
                           const int   x3,                           // координата X первой точки для нахождения границы дуги
                           const int   y3,                           // координата Y первой точки для нахождения границы дуги
                           const int   x4,                           // координата X второй точки для нахождения границы дуги
                           const int   y4,                           // координата Y второй точки для нахождения границы дуги
                           const color clr,                          // Цвет
                           const color fill_clr,                     // Цвет заливки
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPieOnBG(x1,y1,x2,y2,x3,y3,x4,y4,clr,fill_clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Закрашивает область                                              |
//+------------------------------------------------------------------+
bool CAnimations::FillOnBG(const int   id,                           // Идентификатор кадра
                           const int   x,                            // Координата X точки начала закрашивания
                           const int   y,                            // Координата Y точки начала закрашивания
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const uint  threshould=0,                 // Порог
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.FillOnBG(x,y,clr,opacity,threshould,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный прямоугольник                                 |
//+------------------------------------------------------------------+
bool CAnimations::DrawRectangleFillOnBG(const int id,                // Идентификатор кадра
                           const int   x1,                           // Координата X первой точки, определяющей прямоугольник
                           const int   y1,                           // Координата Y первой точки, определяющей прямоугольник
                           const int   x2,                           // Координата X второй точки, определяющей прямоугольник
                           const int   y2,                           // Координата Y второй точки, определяющей прямоугольник
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawRectangleFillOnBG(x1,y1,x2,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный круг                                          |
//+------------------------------------------------------------------+
bool CAnimations::DrawCircleFillOnBG(const int id,                   // Идентификатор кадра
                           const int   x,                            // Координата X центра круга
                           const int   y,                            // Координата Y центра круга
                           const int   r,                            // Радиус круга
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawCircleFillOnBG(x,y,r,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный треугольник                                   |
//+------------------------------------------------------------------+
bool CAnimations::DrawTriangleFillOnBG(const int id,                 // Идентификатор кадра
                           const int   x1,                           // Координата X первой вершины треугольника
                           const int   y1,                           // Координата Y первой вершины треугольника
                           const int   x2,                           // Координата X второй вершины треугольника
                           const int   y2,                           // Координата Y второй вершины треугольника
                           const int   x3,                           // Координата X третьей вершины треугольника
                           const int   y3,                           // Координата Y третьей вершины треугольника
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawTriangleFillOnBG(x1,y1,x2,y2,x3,y3,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный многоугольник                                 |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolygonFillOnBG(const int id,                  // Идентификатор кадра
                           int         &array_x[],                   // Массив, содержащий координаты X точек многоугольника
                           int         &array_y[],                   // Массив, содержащий координаты Y точек многоугольника
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonFillOnBG(array_x,array_y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует закрашенный эллипс, вписанный в прямоугольник             |
//| с заданными координатами                                         |
//+------------------------------------------------------------------+
bool CAnimations::DrawEllipseFillOnBG(const int id,                  // Идентификатор кадра
                           const int   x1,                           // Координата X левого верхнего угла, определяющего прямоугольник
                           const int   y1,                           // Координата Y левого верхнего угла, определяющего прямоугольник
                           const int   x2,                           // Координата X правого нижнего угла, определяющего прямоугольник
                           const int   y2,                           // Координата Y правого нижнего угла, определяющего прямоугольник
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false)                 // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawEllipseFillOnBG(x1,y1,x2,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует точку с использованием алгоритма сглаживания AntiAliasing |
//+------------------------------------------------------------------+
bool CAnimations::SetPixelAAOnBG(const int id,                       // Идентификатор кадра
                           const double x,                           // Координата X точки
                           const double y,                           // Координата Y точки
                           const color  clr,                         // Цвет
                           const uchar  opacity=255,                 // Непрозрачность
                           const bool   create_new=true,             // Флаг создания нового объекта
                           const bool   redraw=false)                // Флаг перерисовки чарта
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.SetPixelAAOnBG(x,y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Рисует отрезок произвольной линии с использованием               |
//| алгоритма сглаживания AntiAliasing                               |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineAAOnBG(const int id,                       // Идентификатор кадра
                           const int   x1,                           // Координата X первой точки отрезка
                           const int   y1,                           // Координата Y первой точки отрезка
                           const int   x2,                           // Координата X второй точки отрезка
                           const int   y2,                           // Координата Y второй точки отрезка
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=UINT_MAX)               // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineAAOnBG(x1,y1,x2,y2,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Рисует отрезок произвольной линии с использованием               |
//| алгоритма сглаживания Wu                                         |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineWuOnBG(const int id,                       // Идентификатор кадра
                           const int   x1,                           // Координата X первой точки отрезка
                           const int   y1,                           // Координата Y первой точки отрезка
                           const int   x2,                           // Координата X второй точки отрезка
                           const int   y2,                           // Координата Y второй точки отрезка
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=UINT_MAX)               // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineWuOnBG(x1,y1,x2,y2,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Рисует отрезок произвольной линии заданной толщины               |
//| с использованием алгоритма сглаживания                           |
//| с предварительной фильтрацией                                    |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineThickOnBG(const int id,                    // Идентификатор кадра
                           const int   x1,                           // Координата X первой точки отрезка
                           const int   y1,                           // Координата Y первой точки отрезка
                           const int   x2,                           // Координата X второй точки отрезка
                           const int   y2,                           // Координата Y второй точки отрезка
                           const int   size,                         // Толщина линии
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=STYLE_SOLID,            // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                           ENUM_LINE_END end_style=LINE_END_ROUND)   // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineThickOnBG(x1,y1,x2,y2,size,clr,opacity,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Рисует вертикальный отрезок произвольной линии заданной толщины  |
//| с использованием алгоритма сглаживания                           |
//| с предварительной фильтрацией                                    |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineThickVerticalOnBG(const int id,            // Идентификатор кадра
                           const int   x,                            // Координата X отрезка
                           const int   y1,                           // Координата Y первой точки отрезка
                           const int   y2,                           // Координата Y второй точки отрезка
                           const int   size,                         // толщина линии
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=STYLE_SOLID,            // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                           const ENUM_LINE_END end_style=LINE_END_ROUND) // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineThickVerticalOnBG(x,y1,y2,size,clr,opacity,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Рисует горизонтальный отрезок произвольной линии заданной толщины|
//| с использованием алгоритма сглаживания                           |
//| с предварительной фильтрацией                                    |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineThickHorizontalOnBG(const int id,          // Идентификатор кадра
                           const int   x1,                           // Координата X первой точки отрезка
                           const int   x2,                           // Координата X второй точки отрезка
                           const int   y,                            // Координата Y отрезка
                           const int   size,                         // толщина линии
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=STYLE_SOLID,            // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                           const ENUM_LINE_END end_style=LINE_END_ROUND) // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineThickHorizontalOnBG(x1,x2,y,size,clr,opacity,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Рисует ломаную линию с использованием                            |
//| алгоритма сглаживания AntiAliasing                               |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolylineAAOnBG(const int id,                   // Идентификатор кадра
                           int         &array_x[],                   // Массив координат X точек ломаной линии
                           int         &array_y[],                   // Массив координат Y точек ломаной линии
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=UINT_MAX)               // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolylineAAOnBG(array_x,array_y,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Рисует ломаную линию с использованием алгоритма сглаживания Wu   |
//+------------------------------------------------------------------+
//--- 
bool CAnimations::DrawPolylineWuOnBG(const int id,                   // Идентификатор кадра
                           int         &array_x[],                   // Массив координат X точек ломаной линии
                           int         &array_y[],                   // Массив координат Y точек ломаной линии
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=UINT_MAX)               // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolylineWuOnBG(array_x,array_y,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Рисует ломаную линию заданной толщины с использованием           |
//| двух алгоритмов сглаживания последовательно.                     |
//| Сначала на основе кривых Безье сглаживаются                      |
//| отдельные отрезки линии.                                         |
//| Затем для повышения качества отрисовки к построенной             |
//| из этих отрезков ломаной линии применяется                       |
//| растровый алгоритм сглаживания                                   |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolylineSmoothOnBG(const int id,               // Идентификатор кадра
                           const int    &array_x[],                  // Массив координат X точек ломаной линии
                           const int    &array_y[],                  // Массив координат Y точек ломаной линии
                           const int    size,                        // Толщина линии
                           const color  clr,                         // Цвет
                           const uchar  opacity=255,                 // Непрозрачность
                           const double tension=0.5,                 // Значение параметра сглаживания
                           const double step=10,                     // Шаг аппроксимации
                           const bool   create_new=true,             // Флаг создания нового объекта
                           const bool   redraw=false,                // Флаг перерисовки чарта
                           const ENUM_LINE_STYLE style=STYLE_SOLID,  // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                           const ENUM_LINE_END   end_style=LINE_END_ROUND) // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolylineSmoothOnBG(array_x,array_y,size,clr,opacity,tension,step,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Рисует ломаную линию заданной толщины с использованием           |
//| алгоритма сглаживания с предварительной фильтрацией              |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolylineThickOnBG(const int id,                // Идентификатор кадра
                           const int      &array_x[],                // Массив координат X точек ломаной линии
                           const int      &array_y[],                // Массив координат Y точек ломаной линии
                           const int      size,                      // Толщина линии
                           const color    clr,                       // Цвет
                           const uchar    opacity=255,               // Непрозрачность
                           const bool     create_new=true,           // Флаг создания нового объекта
                           const bool     redraw=false,              // Флаг перерисовки чарта
                           const uint     style=STYLE_SOLID,         // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                           ENUM_LINE_END  end_style=LINE_END_ROUND)  // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolylineThickOnBG(array_x,array_y,size,clr,opacity,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Рисует многоугольник с использованием                            |
//| алгоритма сглаживания AntiAliasing                               |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolygonAAOnBG(const int id,                    // Идентификатор кадра
                           int         &array_x[],                   // Массив координат X точек многоугольника
                           int         &array_y[],                   // Массив координат Y точек многоугольника
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=UINT_MAX)               // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonAAOnBG(array_x,array_y,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Рисует многоугольник с использованием алгоритма сглаживания Wu   |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolygonWuOnBG(const int id,                    // Идентификатор кадра
                           int         &array_x[],                   // Массив координат X точек многоугольника
                           int         &array_y[],                   // Массив координат Y точек многоугольника
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=UINT_MAX)               // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonWuOnBG(array_x,array_y,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Рисует  многоугольник заданной толщины с использованием          |
//| двух алгоритмов сглаживания последовательно.                     |
//| Сначала на основе кривых Безье сглаживаются отдельные отрезки.   |
//| Затем для повышения качества отрисовки к построенному            |
//| из этих отрезков многоугольнику применяется                      |
//| растровый алгоритм сглаживания.                                  |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolygonSmoothOnBG(const int id,                // Идентификатор кадра
                           int          &array_x[],                  // Массив координат X точек ломаной линии
                           int          &array_y[],                  // Массив координат Y точек ломаной линии
                           const int    size,                        // Толщина линии
                           const color  clr,                         // Цвет
                           const uchar  opacity=255,                 // Непрозрачность
                           const double tension=0.5,                 // Значение параметра сглаживания
                           const double step=10,                     // Шаг аппроксимации
                           const bool   create_new=true,             // Флаг создания нового объекта
                           const bool   redraw=false,                // Флаг перерисовки чарта
                           const ENUM_LINE_STYLE style=STYLE_SOLID,  // Стиль линии — одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
                           const ENUM_LINE_END   end_style=LINE_END_ROUND) // Стиль концов линии — одно из значений перечисления ENUM_LINE_END
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonSmoothOnBG(array_x,array_y,size,clr,opacity,tension,step,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Рисует многоугольник заданной толщины с использованием           |
//| алгоритма сглаживания с предварительной фильтрацией              |
//+------------------------------------------------------------------+
//--- Рисует многоугольник заданной толщины с использованием алгоритма сглаживания с предварительной фильтрацией
bool CAnimations::DrawPolygonThickOnBG(const int id,                 // Идентификатор кадра
                           const int   &array_x[],                   // массив координат X точек многоугольника
                           const int   &array_y[],                   // массив координат Y точек многоугольника
                           const int   size,                         // толщина линии
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=STYLE_SOLID,            // стиль линии

                           ENUM_LINE_END end_style=LINE_END_ROUND)   // стиль концов линии
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonThickOnBG(array_x,array_y,size,clr,opacity,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Рисует треугольник с использованием                              |
//| алгоритма сглаживания AntiAliasing                               |
//+------------------------------------------------------------------+
bool CAnimations::DrawTriangleAAOnBG(const int id,                   // Идентификатор кадра
                           const int   x1,                           // Координата X первой вершины треугольника
                           const int   y1,                           // Координата Y первой вершины треугольника
                           const int   x2,                           // Координата X второй вершины треугольника
                           const int   y2,                           // Координата Y второй вершины треугольника
                           const int   x3,                           // Координата X третьей вершины треугольника
                           const int   y3,                           // Координата Y третьей вершины треугольника
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=UINT_MAX)               // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawTriangleAAOnBG(x1,y1,x2,y2,x3,y3,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Рисует треугольник с использованием алгоритма сглаживания Wu     |
//+------------------------------------------------------------------+
bool CAnimations::DrawTriangleWuOnBG(const int id,                   // Идентификатор кадра
                           const int   x1,                           // Координата X первой вершины треугольника
                           const int   y1,                           // Координата Y первой вершины треугольника
                           const int   x2,                           // Координата X второй вершины треугольника
                           const int   y2,                           // Координата Y второй вершины треугольника
                           const int   x3,                           // Координата X третьей вершины треугольника
                           const int   y3,                           // Координата Y третьей вершины треугольника
                           const color clr,                          // Цвет
                           const uchar opacity=255,                  // Непрозрачность
                           const bool  create_new=true,              // Флаг создания нового объекта
                           const bool  redraw=false,                 // Флаг перерисовки чарта
                           const uint  style=UINT_MAX)               // Стиль линии - одно из значений перечисления ENUM_LINE_STYLE или пользовательское значение
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawTriangleWuOnBG(x1,y1,x2,y2,x3,y3,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Рисует окружность с использованием                               |
//| алгоритма сглаживания AntiAliasing                               |
//+------------------------------------------------------------------+
bool CAnimations::DrawCircleAAOnBG(const int id,                     // Идентификатор кадра
                           const int    x,                           // Координата X центра окружности
                           const int    y,                           // Координата Y центра окружности
                           const double r,                           // Радиус окружности
                           const color  clr,                         // Цвет
                           const uchar  opacity=255,                 // Непрозрачность
                           const bool   create_new=true,             // Флаг создания нового объекта
                           const bool   redraw=