Прежде чем перейти к рассмотрению svg-файлов, хотелось бы остановиться на самом интерпретаторе tcl/tk. Отвечая на один из вопросов, заданных после публикации первой части, я написал, что рассматриваемый проект успешно работает и на tcl/tk версии 9.0.1.
Мне захотелось, чтобы вместе с публикацией второй части статьи был выложен и дистрибутив графического интерпретатора tclexecomp на базе девятой версии tcl/tk. Однако выпуск версии tclexecomp для tcl/tk-9 задерживается и было решено собрать дистрибутив самостоятельно. Уже имея опыт сборки проекта Bawt для tcl/tk-9.0.1, удалось после нескольких дней работы собрать и дистрибутив tclexecomp с tcl/tk-9.0.1, с включёнными в него пакетами проекта svgwidgets. И всё было замечательно, все тестовые примеры работали. Но тут случайно мною была на клавиатуре нажата клавиша Backspace и произошел крах интерпретатора. После проверки остальных клавиш выяснилось, что аналогичный эффект происходит при нажатии клавиш Left и Right. Сначала я подумал, что это мои косяки, но решил проверить работу этих клавиш на виджетах text
, entry
и ttk::entry
, в которых для редактирования текста используются эти клавиши. И тут выяснялось, что нажатие на эти клавиши приводит к краху интерпретатора wish9.0, т. е. собранная версия графического интерпретатора tclexecomp здесь ни при чём.
Честно говоря, я не стал проверять работу этих клавиш на первой версии tcl/tk-9.0.0. Первым порывом было написать письмо разработчикам tcl/tk, но прежде я решил посмотреть, как идут дела у разработчиков с подготовкой очередного релиза. И здесь меня ждал приятный сюрприз. В файле изменений для tk-9.0.2 присутствует такая запись: Backspace crashes 9.0 interpreter on FreeBSD.
Это было то, с чем столкнулся я. Правда здесь речь идёт о FreeBSD, а у меня Linux, но я решил проверить. Проверка дала положительный результат и больше проблем с клавиатурой я не наблюдал. Собранный интерпретатор со всеми пакетами svgwidgets под именем tclexecomp64_902_Lin64 добавлен в проект TkSVGWidgets на GitHub-е в папку tclexecomp902. Всем, кто будет тестировать проект, необходимо его скачать заново с GitHub. А теперь возвращаемся к основному материалу.
SVG-файлы представляют собой текстовые файлы с расширением .svg
, содержащие xml-код, описывающий изображения в виде геометрических примитивов: линий, кривых, фигур, текста и т.д.
В tk-9.0 добавлена частичная поддержка svg-графики, которая позволяет использовать svg-иконки в GUI. Для этого сначала создается изображение:
image create photo [<идентификатор изображения>] [-format {svg [-scale <масштабирование> | -scaletowidth <ширина> | -scaletoheight <высота>]}
Данный оператор всегда возвращает идентификатор изображения. Параметр scale
задает масштаб изображения относительно исходного. Параметр scaletowidth
указывает требуемую ширину изображения. Пропорционально изменению ширины будет установлена и высота изображения. Аналогично работает и параметр scaletoheight
.
Менять размер изображения можно и командой configure
:
<идентификатор изображения> configure -format {svg [-scale <масштабирование> | -scaletowidth <ширина> | -scaletoheight <высота>]
Помимо того, что нельзя изменить соотношение сторон, также есть проблемы с отображением градиентной заливки и стрелок.
Это классика, а мы говорим об svg-виджетах и здесь этих проблем нет.
Для демонстрации запустим интерпретатор tclexecomp64_902_Lin64.
После запуска интерпретатора и загрузки пакета svg2can достаточно выполнить несколько команд, чтобы на холсте появилось изображение из файла svgimages/Action_launch.svg:
#Загружвем пакет svg2can
package require svg2can
#Создаем окно проекта
toplevel .t -background cyan
#Геометрия окна
wm geometry .t 380x640
#Создаем холст tkp::canvas
tkp::canvas .t.c -bg yellow -width 500 -height 450
#Размещаем холст в окне
pack .t.c -fill both -expand 1
#Размещаем на холсте картинку из svg-файла
set idsvg [svg2can::SVGFileToCanvas .t.c svgimages/Action_launch.svg]
winfo class .win.c
#Координаты картинки на холсте
set coordsid [.t.c bbox $idsvg]
В данном примере для отображения на холсте картинки используется команда svg2can::SVGFileToCanvas
из пакета svg2can, которая имеет следующий формат:
svg2can::SVGFileToCanvas <tkp-холст> <путь к svg-файлу>
Xml-код картинки необязательно должен храниться в файле, его можно задавать явно в виде константы или как значение tcl-переменной. В этом случае используется команда следующего вида:
svg2can::SVGXmlToCanvas <path-холст> <xml-код>
Команды svg2can::SVGFileToCanvas
и svg2can::SVGXmlToCanvas
при успешном выполнении возвращают идентификатор группы (далее просто группа), в которой сгруппированы все элементы картинки. Чтобы получить все идентификаторы элементов картинки, достаточно выполнить команду:
<холст с картинкой> children <идентификатор группы>
Очевидно, что рисунок на холсте должен располагаться в определенном месте и иметь определенные размеры. Для перемещения картинки в соответствующие координаты и установления требуемого размера служит команда копирования группы:
svg2can::copy <холст с картинкой> <холст назначения> <группа> [<параметры>]
Эта команда копирует заданную картинку (<холст с картинкой> и <группа>) на указанный <холст назначения> и возвращает идентификатор группы на холсте назначения. Естественно, копирование может производиться и в рамках одного холста. После копирования оригинал может быть (если он больше не потребуется) уничтожен:
<холст с картинкой> delete <идентификатор группы>
Координаты клона на заданном холсте задаются списком параметров:
-x <координата по оси X>
-y <координата по оси Y>
-width <ширина картинки>
-height <высота картинки>
Для примера клонируем нашу картинку, при этом ширину картинки увеличим в полтора раза, а высоту увеличим в три раза и расположим справа от эталона. Размеры оригинала определим, выполнив команду bbox
:
#Вычисляем координаты орининала
lassign [.t.c bbox $idsvg] x0 y0 x1 y1
#Создаем клон ракеты
::svg2can::copy .t.c .t.c $idsvg -x $x1 -y $y1 -width [expr {($x1 - $x0) * 1.5}] -height [expr {($y1 - $y0) * 3}]
Результат можно увидеть в центре скриншота, в начале статьи.
Итак, svg-изображение характеризуется двумя параметрами: именем холста, на котором оно размещено, и номером группы на этом холсте. SVG-изображения, так же как и классические изображения (image) могут использоваться как иконки в виджетах классов ibutton
и cbutton
. В классе cbutton
иконки применимы к типам rect
и square
. Классические иконки задаются их идентификаторами, а svg
-изображения задаются парой (списком)
-image | -isvg [list <svg-холст> <идентификатор группы>]
или
-image | -isvg "<svg-холст> <идентификатор группы>"
Ниже представлен код, который добавляет кнопку «Старт» с иконкой в виде ракеты:
#Загружаем пакет svgwidgets
package require svgwidgets
#Устанавливаем высоту холста
.t.c configure -height 520
#Создаём кнопку «Старт»
set idlauch [cbutton new .t.b2 -text Старт -image ".t.c $idsvg" -rx 10 -strokewidth 3]
#Устанавливает характеристика шрифта
$idlauch config -fontsize 29 -textfill red -textstroke yellow -fontweight bold
#Размещаем иконку в окне
pack [$idlauch canvas] -fill both -expand 1 -padx 2c -pady 5m
Можно «поиграться» геометрией главного окна (например, перемещая правый нижний угол окна) и посмотреть как будет видоизменяться иконка с ракетой.
На Linux в каталоге /usr/share/icons можно найти много svg-файлов. Для их просмотра были написаны тестовые утилиты svgTestOrigToSVGWIDGET_Pack.tcl
и svgtesttocan.tcl
, которые находятся в каталоге examples.
К svg-изображениям можно применять различные трансформации (перемещение, масштабирование, поворот, смещение по осям X и Y). Увидеть, как это работает, можно, запустив утилиту examples/svgFileToCan.tcl
. Результат работы этого скрипта можно видеть в правой нижней четверти скриншота в начале статьи.
Для комплексной демонстрации возможностей проекта svgwidgets в хранилище проекта на GitHub-е добавлен каталог examples/CryptoArmPKCS_Test, в котором лежит демонстрационный код криптографической утилиты cryptoatmpkcs_svg для работы с электронной подписью. Для ее запуска следует воспользоваться интерпретатором tclexecomp64_902_Lin64:
$tclexecomp64_902_Lin64 examples/CryptoArmPKCS_Test/mainguipkcs_svg.tcl
Стартовую страницу этой утилиты можно видеть в правой верхней четверти скриншота в начале статьи.