вывод изображения осуществляется с помощью дисплейных списков,
т.е. команд управления режимами отрисовки и выводом графических примитивов
при этом в таких примитивах, как линия, прямоугольник итд в качестве координат используются мировые координаты
объект TDrawer связан с полотном, на котором производится рисование
имеет параметры отображаемой области, масштаб, поворот и для преобразования мировых координат в экранные
и является по сути интерпретатором команд дисплейного списка
список поддерживаемых команд (реализованы не все!)
01 Set var=value
02 Unset var
04 SetWidth x
03 SetColor n
05 SetBGColor n
06 SetFont font,size,color,bius
работает через установку свойств Font для Canvas.
TextOut, выполненный непосредственно после него, отрисует надпись шрифтом именно такого размера
19 SetScaledFont font,height,scale,color,bius
устанавливает высоту шрифта по формуле Canvas.Font.Height:=Round(StrToFloat(FontSize)/Self.ViewScale);
10 MoveTo x,y
09 LineTo x,y
11 Rect x1,y1,x2,y2
12 RoundRect x1,y1,x2,y2
08 Ellipse x1,y1,x2,y2
13 Circle x,y,r
14 TextOut x,y,text
выводит однострочный текст, начиная от точки с указанными координатами
работает через Canvas.TextRect(Rect(Xs,Ys,Xs+Canvas.GetTextWidth(FName)
т.е. надпись будет выведена полностью, без обрезания по прямоугольнику
15 Bmp x1,y1,x2,y2,cachename
16 SubPicture x,y,x2,y2,filename
17 SetTextStyle opaque
18 SetPenStyle psDot
20 UnScaled box1,pixelsize
21 TextRect x1,y1,x2,y2,text
выводит многострочный текст с отсечкой по границам заданного прямоугольника
если x2,y2 равны 0, то без отсечки
работает через Canvas.TextRect(Rect(Xs,Ys,X2s,Y2s),Xs,Ys,MultiLine.Text,TextStyle);
07 floodfill x,y,color
При многократном исполнении дисплейного списка (например при навигации по сцене, т.е. скроллинге и смене масштаба)
каждый раз будет анализироваться текстовая строка и выполняться преобразование координат из текстового формата в вещественный
Чтобы сэкономить вычислительные ресурсы - интерпретатору команд передаётся не только текстовое представление команды, но и
"акселератор" - структура данных, несущая координаты уже в вещественной форме и код команды вместо её текстового имени для ускорения сравнения
Команды, содержащие текстовые атрибуты наподобие имени файла или шрифта будут парситься в любом случае
Пример использования акселератора для многократно отрисовываемого участка (например объект на сцене)
NonAccCommand:='SetColor '+Connection.Color;
AccObject:=TAccObject.Create;
AccObject.AcceleratedCommand:=AccelerateCommand(NonAccCommand);
Connection.DisplayList.AddObject(NonAccCommand,AccObject);
Если какой-то объект должен быть нарисован всего один раз, например с целью подсветки выделения
или рисования "ручек" вокруг объекта или необходимо выполнить команду, которая будет парситься в любом случае,
и организовывать ускорение бессмысленно, то можно воспользоваться "нулевым акселератором"
ZeroAcc: TAcceleratedCommand=(0,0,0,0,0);
Drawer.ExecCommand('MoveTo '+FloatToStr(Curl.Shell.X1)+','+FloatToStr(Curl.Shell.Y1),ZeroAcc);
По сути акселертор является кешем распарсенной строки.
К сожалению кешировать результат преобразования мировых координат в экранные практически бесполезно, т.к. при каждом
перемещении изменении масштаба отображения и начала координат матрица преобразования обновляется и такой кеш мгновенно устаревает.
Если необходимо перерисовать сцену не вследствие её модификации, а по внешней причине (окно заслонили другим окном) -
то вызывается не полный рендеринг, а вывод растрового буфера.
Кеширование экранных координат может пригодиться при полной перерисовке сцены при её частичном изменении сцены без смены
позиционирования (копирование множества объектов, автоматической трассировке соединений), но только если эффективно
решить вопрос инвалидации кеша для команд, принадлежащих модифицируемым дисплейным спискам.
SubPicture - для векторных контейнеров
берет из кеша (если там нет - то зазгружает) дисплейный список
расчитывает его прямоугольную оболочку, генерирует субдравер с матрицей,
вписывающей расчитанную оболочку в заданный прямоугольник
и исполняет команды на нём