42.17.6 Изображения SVG

SVG (масштабируемая векторная графика) — это формат XML для описания изображений. Изображения SVG поддерживают следующие дополнительные свойства дескриптора изображения:

:foreground foreground

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

:background background

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

:css css

css, если не равно nil, должно быть строкой, задающей CSS для переопределения CSS по умолчанию, используемого при создании изображения.

Библиотека SVG

Если ваша сборка Emacs имеет поддержку SVG, вы можете создавать и управлять этими изображениями с помощью следующих функций из библиотеки svg.el.

Функция: svg-create width height &rest args

Создаёт новое пустое изображение SVG указанных размеров. args — это список аргументов в виде plist, в котором можно задать следующее:

:stroke-width

Ширина (в пикселях) по умолчанию для любых создаваемых линий.

:stroke

Цвет обводки по умолчанию для любых создаваемых линий.

Эта функция возвращает объект SVG — структуру данных Lisp, определяющую изображение SVG. Все следующие функции работают с этой структурой. Аргумент svg в следующих функциях задаёт такой объект SVG.

Функция: svg-gradient svg id type stops

Создаёт градиент в svg с идентификатором id. type задаёт тип градиента и может быть либо linear (линейный), либо radial (радиальный). stops — это список пар процент/цвет.

Следующий пример создаёт линейный градиент, который идёт от красного в начале, через зелёный на 25% пути, к синему в конце:

(svg-gradient svg "gradient1" 'linear
              '((0 . "red") (25 . "green") (100 . "blue")))

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

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

:stroke-width

Ширина (в пикселях) рисуемых линий и контуров вокруг залитых фигур.

:stroke-color

Цвет рисуемых линий и контуров вокруг залитых фигур.

:fill-color

Цвет, используемый для залитых фигур.

:id

Идентификатор фигуры.

:gradient

Если задан, должен быть идентификатором ранее определённого объекта градиента.

:clip-path

Идентификатор пути обрезки.

Функция: svg-rectangle svg x y width height &rest args

Добавляет в svg прямоугольник, левый верхний угол которого находится в позиции x/y, а размер равен width/height.

(svg-rectangle svg 100 100 500 500 :gradient "gradient1")
Функция: svg-circle svg x y radius &rest args

Добавляет в svg окружность с центром в x/y и радиусом radius.

Функция: svg-ellipse svg x y x-radius y-radius &rest args

Добавляет в svg эллипс с центром в x/y, и горизонтальным радиусом x-radius и вертикальным радиусом y-radius.

Функция: svg-line svg x1 y1 x2 y2 &rest args

Добавляет в svg линию, начинающуюся в x1/y1 и заканчивающуюся в x2/y2.

Функция: svg-polyline svg points &rest args

Добавляет в svg многосегментную линию (также называемую «полилинией»), проходящую через points, который является списком пар позиций X/Y.

(svg-polyline svg '((200 . 100) (500 . 450) (80 . 100))
              :stroke-color "green")
Функция: svg-polygon svg points &rest args

Добавляет многоугольник в svg, где points — это список пар X/Y, описывающих внешнюю границу многоугольника.

(svg-polygon svg '((100 . 100) (200 . 150) (150 . 90))
             :stroke-color "blue" :fill-color "red")
Функция: svg-path svg commands &rest args

Добавляет контур фигуры в svg согласно commands. Смотрите Команды пути SVG.

Координаты по умолчанию являются абсолютными. Чтобы использовать координаты относительно последней позиции или — изначально — относительно начала координат, установите атрибут :relative в t. Этот атрибут можно задать для функции или для отдельных команд. Если он задан для функции, то все команды по умолчанию используют относительные координаты. Чтобы отдельная команда использовала абсолютные координаты, установите :relative в nil.

(svg-path svg
	  '((moveto ((100 . 100)))
	    (lineto ((200 . 0) (0 . 200) (-200 . 0)))
	    (lineto ((100 . 100)) :relative nil))
	  :stroke-color "blue"
	  :fill-color "lightblue"
	  :relative t)
Функция: svg-text svg text &rest args

Добавляет указанный text в svg.

(svg-text
 svg "Это текст"
 :font-size "40"
 :font-weight "bold"
 :stroke "black"
 :fill "white"
 :font-family "impact"
 :letter-spacing "4pt"
 :x 300
 :y 400
 :stroke-width 1)
Функция: svg-embed svg image image-type datap &rest args

Добавляет встроенное (растровое) изображение в svg. Если datap равно nil, image должно быть именем файла; в противном случае это должна быть строка, содержащая данные изображения в виде сырых байтов. image-type должен быть MIME-типом изображения, например "image/jpeg".

(svg-embed svg "~/rms.jpg" "image/jpeg" nil
           :width "100px" :height "100px"
           :x "50px" :y "75px")
Функция: svg-embed-base-uri-image svg relative-filename &rest args

Добавляет в svg встроенное (растровое) изображение, расположенное по пути relative-filename. relative-filename ищется внутри file-name-directory свойства изображения SVG :base-uri. :base-uri задаёт (возможно несуществующее) имя файла создаваемого изображения SVG, поэтому все встраиваемые файлы ищутся относительно каталога имени файла :base-uri. Если :base-uri опущен, используется имя файла, из которого загружается изображение SVG. Использование :base-uri повышает производительность встраивания больших изображений по сравнению с svg-embed, поскольку вся работа выполняется непосредственно librsvg.

;; Встраивание /tmp/subdir/rms.jpg и /tmp/another/rms.jpg
(svg-embed-base-uri-image svg "subdir/rms.jpg"
           :width "100px" :height "100px"
           :x "50px" :y "75px")
(svg-embed-base-uri-image svg "another/rms.jpg"
           :width "100px" :height "100px"
           :x "75px" :y "50px")
(svg-image svg :scale 1.0
           :base-uri "/tmp/dummy"
           :width 175 :height 175)
Функция: svg-clip-path svg &rest args

Добавляет путь обрезки в svg. Если он применён к фигуре через свойство :clip-path, части этой фигуры, которые находятся вне пути обрезки, не отрисовываются.

(let ((clip-path (svg-clip-path svg :id "foo")))
  (svg-circle clip-path 200 200 175))
(svg-rectangle svg 50 50 300 300
               :fill-color "red"
               :clip-path "url(#foo)")
Функция: svg-node svg tag &rest args

Добавляет пользовательский узел tag в svg.

(svg-node svg
          'rect
          :width 300 :height 200 :x 50 :y 100 :fill-color "green")
Функция: svg-remove svg id

Удаляет элемент с идентификатором id из svg.

Функция: svg-image svg

Наконец, функция svg-image принимает объект SVG в качестве аргумента и возвращает объект изображения, пригодный для использования в таких функциях, как insert-image.

Вот полный пример, который создаёт и вставляет изображение с окружностью:

(let ((svg (svg-create 400 400 :stroke-width 10)))
  (svg-gradient svg "gradient1" 'linear '((0 . "red") (100 . "blue")))
  (svg-circle svg 200 200 100 :gradient "gradient1"
                  :stroke-color "green")
  (insert-image (svg-image svg)))

Команды пути SVG

Пути SVG позволяют создавать сложные изображения путём комбинирования линий, кривых, дуг и других базовых фигур. Описанные ниже функции позволяют вызывать команды пути SVG из программы на Lisp.

Команда: moveto points

Перемещает перо в первую точку в points. Дополнительные точки соединяются линиями. points — это список пар координат X/Y. Последующие команды moveto обозначают начало нового подпути.

(svg-path svg '((moveto ((200 . 100) (100 . 200) (0 . 100))))
          :fill "white" :stroke "black")
Команда: closepath

Завершает текущий подпуть, соединяя его обратно с начальной точкой. Вдоль соединения рисуется линия.

(svg-path svg '((moveto ((200 . 100) (100 . 200) (0 . 100)))
                (closepath)
                (moveto ((75 . 125) (100 . 150) (125 . 125)))
                (closepath))
          :fill "red" :stroke "black")
Команда: lineto points

Рисует линию от текущей точки до первого элемента в points — списке пар позиций X/Y. Если указано более одной точки, рисуется полилиния.

(svg-path svg '((moveto ((200 . 100)))
                (lineto ((100 . 200) (0 . 100))))
          :fill "yellow" :stroke "red")
Команда: horizontal-lineto x-coordinates

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

(svg-path svg '((moveto ((100 . 200)))
                (horizontal-lineto (300)))
          :stroke "green")
Команда: vertical-lineto y-coordinates

Рисует вертикальные линии.

(svg-path svg '((moveto ((200 . 100)))
                (vertical-lineto (300)))
          :stroke "green")
Команда: curveto coordinate-sets

Используя первый элемент в coordinate-sets, рисует кубическую кривую Безье от текущей точки. Если имеется несколько наборов координат, рисуется полибезье. Каждый набор координат имеет вид (x1 y1 x2 y2 x y), где (x, y) — конечная точка кривой. (x1, y1) и (x2, y2) — управляющие точки в начале и в конце соответственно.

(svg-path svg '((moveto ((100 . 100)))
                (curveto ((200 100 100 200 200 200)
                          (300 200 0 100 100 100))))
          :fill "transparent" :stroke "red")
Команда: smooth-curveto coordinate-sets

Используя первый элемент в coordinate-sets, рисует кубическую кривую Безье от текущей точки. Если имеется несколько наборов координат, рисуется полибезье. Каждый набор координат имеет вид (x2 y2 x y), где (x, y) — конечная точка кривой, а (x2, y2) — соответствующая управляющая точка. Первая управляющая точка является отражением второй управляющей точки предыдущей команды относительно текущей точки, если этой командой была curveto или smooth-curveto. В противном случае первая управляющая точка совпадает с текущей точкой.

(svg-path svg '((moveto ((100 . 100)))
                (curveto ((200 100 100 200 200 200)))
                (smooth-curveto ((0 100 100 100))))
          :fill "transparent" :stroke "blue")
Команда: quadratic-bezier-curveto coordinate-sets

Используя первый элемент в coordinate-sets, рисует квадратичную кривую Безье от текущей точки. Если имеется несколько наборов координат, рисуется полибезье. Каждый набор координат имеет вид (x1 y1 x y), где (x, y) — конечная точка кривой, а (x1, y1) — управляющая точка.

(svg-path svg '((moveto ((200 . 100)))
                (quadratic-bezier-curveto ((300 100 300 200)))
                (quadratic-bezier-curveto ((300 300 200 300)))
                (quadratic-bezier-curveto ((100 300 100 200)))
                (quadratic-bezier-curveto ((100 100 200 100))))
          :fill "transparent" :stroke "pink")
Команда: smooth-quadratic-bezier-curveto coordinate-sets

Используя первый элемент в coordinate-sets, рисует квадратичную кривую Безье от текущей точки. Если имеется несколько наборов координат, рисуется полибезье. Каждый набор координат имеет вид (x y), где (x, y) — конечная точка кривой. Управляющая точка является отражением управляющей точки предыдущей команды относительно текущей точки, если этой командой была quadratic-bezier-curveto или smooth-quadratic-bezier-curveto. В противном случае управляющая точка совпадает с текущей точкой.

(svg-path svg '((moveto ((200 . 100)))
                (quadratic-bezier-curveto ((300 100 300 200)))
                (smooth-quadratic-bezier-curveto ((200 300)))
                (smooth-quadratic-bezier-curveto ((100 200)))
                (smooth-quadratic-bezier-curveto ((200 100))))
          :fill "transparent" :stroke "lightblue")
Команда: elliptical-arc coordinate-sets

Используя первый элемент в coordinate-sets, рисует эллиптическую дугу от текущей точки. Если имеется несколько наборов координат, рисует последовательность эллиптических дуг. Каждый набор координат имеет вид (rx ry x y), где (x, y) — конечная точка эллипса, а (rx, ry) — его радиусы. К списку могут быть добавлены атрибуты:

:x-axis-rotation

Угол в градусах, на который повёрнута ось X эллипса относительно оси X текущей системы координат.

:large-arc

Если установлен в t, рисует дугу с углом раствора больше или равным 180 градусам. В противном случае рисует дугу с углом раствора меньше или равным 180 градусам.

:sweep

Если установлен в t, рисует дугу в направлении положительного угла. В противном случае рисует её в направлении отрицательного угла.

(svg-path svg '((moveto ((200 . 250)))
                (elliptical-arc ((75 75 200 350))))
          :fill "transparent" :stroke "red")
(svg-path svg '((moveto ((200 . 250)))
                (elliptical-arc ((75 75 200 350 :large-arc t))))
          :fill "transparent" :stroke "green")
(svg-path svg '((moveto ((200 . 250)))
                (elliptical-arc ((75 75 200 350 :sweep t))))
          :fill "transparent" :stroke "blue")
(svg-path svg '((moveto ((200 . 250)))
                (elliptical-arc ((75 75 200 350 :large-arc t
                                     :sweep t))))
          :fill "transparent" :stroke "gray")
(svg-path svg '((moveto ((160 . 100)))
                (elliptical-arc ((40 100 80 0)))
                (elliptical-arc ((40 100 -40 -70
                                     :x-axis-rotation -120)))
                (elliptical-arc ((40 100 -40 70
                                     :x-axis-rotation -240))))
          :stroke "pink" :fill "lightblue"
          :relative t)