Регистрация | Войти
Lisp — программируемый язык программирования

Vecto - Простая векторная графика с Common Lisp'ом

Введение

Vecto это упрощенный интерфейс к мощной библиотеки векторной растеризации CL-VECTORS. Vecto предоставляет функциональный интерфейс похожий на CL-PDF, и результат может быть сохранен в PNG, вместо PDF файла. Библиотека и зависимости написаны на Common Lisp'е, без использования сторонних не-лисп библиотек. Весь стек должен работать в любом Common Lisp окружении. Vecto доступна по BSD-like лицензией. Текущая версия 1.4.3, опубликована 26 августа 2009 года.

Vecto используется такими ресурсами как Easystreet и Movie Charts.

Домашняя страничка проекта: http://www.xach.com/lisp/vecto/.

Ссылка для загрузки: http://www.xach.com/lisp/vecto.tgz

Обзор возможностей

Vecto - это библиотека, предоставляющая простой интерфейс к библиотеке векторной графики CL-VECTORS. Она подерживает рисование на холсте и сохранение результатов в PNG файл.

Vecto зависит от следующих библиотек:

Примечание переводчика: простой путь установки - через quicklisp

(ql:quickload :vecto)

ASDF-Install - это простой путь для установки Vecto и всех зависимостей.

Функциональный интерфейс Vecto подобен интерфейсам описания векторов и рисования изображений PDF: вы создаете изображения описанием контуров вектора, затем используете stroke или fill операции для рисования на холсте.

Цветовая система использует 4 канала: красный, зеленый, синий и альфа. Результаты сохраняются в PNG файл с альфа каналом.

Координатная система имеет точку отсчета в левом нижнем углу изображения, и вектор (1, 1) направлен вправо вверх.

Все размеры указываются в пикселях.

PDF система очень богата возможностями. Vecto поддерживает стиль лишь небольшого их подмножества. В частности она не поддерживает:

  • sampled images
  • шаблонная или функциональная заливка
  • сложное позиционирование текста
  • Шрифты PostScript
  • не-RGB цвета

Другие ограничения:

  • Нет вывода в формате отличном от 8 битного truecolor-alpha PNG.
  • Нет доступа к пикселям

Родственные библиотеки:

Примеры

Все примеры доступны в doc/examples.lisp в дистрибутиве Vecto. Этот файл начинается с:

(defpackage #:vecto-examples
  (:use #:cl #:vecto)
)


(in-package #:vecto-examples)
(defun radiant-lambda (file)
  (with-canvas (:width 90 :height 90)
    (let ((font (get-font "times.ttf"))
          (step (/ pi 7))
)

      (set-font font 40)
      (translate 45 45)
      (draw-centered-string 0 -10 #(#x3BB))
      (set-rgb-stroke 1 0 0)
      (centered-circle-path 0 0 35)
      (stroke)
      (set-rgba-stroke 0 0 1.0 0.5)
      (set-line-width 4)
      (dotimes (i 14)
        (with-graphics-state
          (rotate (* i step))
          (move-to 30 0)
          (line-to 40 0)
          (stroke)
)
)

      (save-png file)
)
)
)

Изображение

(defun feedlike-icon (file)
  (with-canvas (:width 100 :height 100)
    (set-rgb-fill 1.0 0.65 0.3)
    (rounded-rectangle 0 0 100 100 10 10)
    (fill-path)
    (set-rgb-fill 1.0 1.0 1.0)
    (centered-circle-path 20 20 10)
    (fill-path)
    (flet ((quarter-circle (x y radius)
             (move-to (+ x radius) y)
             (arc x y radius 0 (/ pi 2))
)
)

      (set-rgb-stroke 1.0 1.0 1.0)
      (set-line-width 15)
      (quarter-circle 20 20 30)
      (stroke)
      (quarter-circle 20 20 60)
      (stroke)
)

    (rounded-rectangle 5 5 90 90 7 7)
    (set-gradient-fill 50 90
                       1.0 1.0 1.0 0.7
                       50 20
                       1.0 1.0 1.0 0.0
)

    (set-line-width 2)
    (set-rgba-stroke 1.0 1.0 1.0 0.1)
    (fill-and-stroke)
    (save-png file)
)
)

Изображение

(defun star-clipping (file)
  (with-canvas (:width 200 :height 200)
    (let ((size 100)
          (angle 0)
          (step (* 2 (/ (* pi 2) 5)))
)

      (translate size size)
      (move-to 0 size)
      (dotimes (i 5)
        (setf angle (+ angle step))
        (line-to (* (sin angle) size)
                 (* (cos angle) size)
)
)

      (even-odd-clip-path)
      (end-path-no-op)
      (flet ((circle (distance)
               (set-rgba-fill distance 0 0
                              (- 1.0 distance)
)

               (centered-circle-path 0 0 (* size distance))
               (fill-path)
)
)

        (loop for i downfrom 1.0 by 0.05
              repeat 20 do
              (circle i)
)
)

      (save-png file)
)
)
)

Изображение

Dictionary

API

The following symbols are exported from the VECTO package. Из пакета Vecto экспортируются следующие символы:

Canvases

Холсты

[Macro]
with-canvas (&key width height) &body body

Исполняет body с холстом с указанными размерам для команд рисования. Холст после создания полностью чист (все пиксели имеют значение альфа канала равное нулю).

[Function]
clear-canvas => |

Полностью заполняет холст текущим цветом заливки. Любые знаки на холсте будут очищены.

[Function]
save-png file => truename

Записывает содержимое холста в PNG файл, и возвращает имя файла.

[Function]
save-png-stream stream => |

Записывает содержимое холста как PNG в поток, который должен принимать (unsigned 8) данные.

Состояния

Состояния сохраняют несколько параметров используемых операциями рисования.

[Macro]
with-graphics-state &body body

Выполняет формы body с копией текущего состояния. Любые модификации этого состояния будут отменены в конце данной формы.

[Functions]
set-rgba-fill r g b alpha => |
set-rgb-fill r g b => |

Устанавливает цвет заливки. r, g, b и alpha должны быть в интервале от 0.0 до 1.0.

  set-rgb-fill is the same as set-rgba-fill with an implicit alpha value of 1.0.

set-rgb-fill это то же, что и set-rgba-fill с установленным значением альфа канала в 1.0.

Цвет заливки используется командами CLEAR-CANVAS, FILL-PATH, EVEN-ODD-FILL, FILL-AND-STROKE, EVEN-ODD-FILL-AND-STROKE и DRAW-STRING.

[Function]
set-gradient-fill x0 y0 r0 g0 b0 a0 x1 y1 r1 g1 b1 a1 &key (extend-start t) (extend-end t) (domain-function 'linear-domain)

Устанавливает в качестве цвета заливки градиент. Начальная точка - x0, y0 и начальный цвет r0,g0,b0,a0. Конечная точка x1, y1 и конечный цвет r1, g1, b1, a1.

Доступны две функции для типа градиента:

  • LINEAR-DOMAIN, по-умолчанию, создает переход от начального цвета в конечный цвет вдоль оси от начальной точки к конечной.
  • BILINEAR-DOMAIN создает переход от начального цвета к конечному от начальной точки в серединной, а затем от серединной через начальную к конечной.
(defun gradient-example (file)
  (with-canvas (:width 200 :height 50)
    (set-gradient-fill 25 0
                       1 0 0 1
                       175 0
                       1 0 0 0
)

    (rectangle 0 0 200 50)
    (fill-path)
    (save-png file)
)
)

Изображение

(defun gradient-bilinear-example (file)
  (with-canvas (:width 200 :height 50)
    (set-gradient-fill 25 0
                       1 0 0 1
                       175 0
                       1 0 0 0
                       :domain-function 'bilinear-domain
)

    (rectangle 0 0 200 50)
    (fill-path)
    (save-png file)
)
)

Изображение

[Functions]
set-rgba-stroke r g b alpha => |
set-rgb-stroke r g b => |

Устанавливает цвет контуров. r, g, b и alpha должны быть в интервале от 0.0 по 1.0.

set-rgb-stroke это то же, что и set-rgba-stroke с установленным значением альфа канала в 1.0.

Цвет контуров используется в функциях STROKE, FILL-AND-SROKE и EVEN-ODD-FILL-AND-STROKE.

[Function]
set-line-cap style => |

Устанавливает стиль концов линий, которым может быть одним из :BUTT, :SQUARE, или :ROUND

ИзображениеИзображениеИзображение
:BUTT:SQUARE:ROUND
[Function]
set-line-join style => |

Устанавливает стиль углов ломанной. Может быть одним из: :MITER, :BEVEL или :ROUND.

ИзображениеИзображениеИзображение
:MITER:BEVEL:ROUND
[Function]
set-line-width width => |

Устанавливает толщину линии контура в width.

[Function]
set-dash-pattern dash-vector phase => |

Устанавливает шаблон штриховки согласно dash-vector и phase.

dash-vector должен быть вектором значений для включения и выключения рисования контура. Пустой вектор эквивалентен отсутствию шаблона.

phase определяет, насколько должен быть смещен шаблон перед тем, как применить его к контуру.

Appearance Dash Vector and Phase
Изображение #() 0
Изображение #(30 30) 0
Изображение #(30 30) 15
Изображение #(10 20 10 40) 0
Изображение #(10 20 10 40) 13
Изображение #(30 30) 0, :ROUND line caps
[Function]
translate x y => |

Перемещает систему координат на x по оси X и на y по оси Y.

[Function]
rotate radians => |

Поворачитвает систему координат на угол radians (в радианах).

[Function]
scale sx sy => |

Масштабирует систему координат на sx по оси X и на sy по оси Y.

[Function]
skew ax ay => |

Наклоняет ось X системы координат на ax радиан и Y ось на ay радиан.

[Function]
clip-path => |

Определяет область отсечения, которая базируется на текущем векторе. Область применяется не сразу, но она создается после того, как рисование закончено, в следующем вызове одной из функций: FILL-PATH, EVEN-ODD-FILL, FILL-AND-SROKE, EVEN-ODD-FILL-AND-STROKE или END-PATH-NO-OP.

Первоначально область отсечения применяется на всем холсте. Последующие вызовы CLIP-PATH устанавливают область отсечения в контексте предыдущего установленного отсечения.

  The outline of the clipping path is defined with the nonzero winding rule, as with FILL-PATH FIXME.

Не существует возможности увеличить область отсечения. Так как, область отсечения является частью состояния, то изменения могут быть локализованы использованием WITH-GRAPHICS-STATE.

ИзображениеЗаполненный красный прямоугольник
ИзображениеТот же прямоугольник с применным круговым правилом отсечения
ИзображениеОбласть отсечения - прямоугольник со скругленными углами
ИзображениеПересечение двух областей отсечения: круга и прямоугольника
[Function]
even-odd-clip-path => |

Как CLIP-PATH, но использует четные/нечетные правила заливки, чтобы определить контур отсечения FIXME.

Контуры

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

[Function]
move-to x y => |

Начинает новый одконтур в точке (x, y). move-to должна быть первой функцией создания подконтура.

[Function]
line-to x y => |

Добавляет прямую линию заканчивающуюся в (x, y) к данному подконтуру.

[Function]
curve-to cx1 cy1 cx2 cy2 x y => |

Добавляет кубическую кривую Безье заканчивающуюся в (х, у) с контрольными точками (cx1, cy1) и (cx2, су2) к текущему подконтуру.

[Function]
quadratic-to cx cy x y => |

Добавляет квадратичную кривую Безье заканчивающуюся в (х, у) с контрольными точками (cx, cy) к текущему подконтуру.

[Function]
arc x y radius angle1 angle2 => |

Добавляет дугу окружности к данному контуру. Центер дуги в (x, y). Дуга начинается в точке на расстоянии радиуса от центра под углом (в радианах) angle1 начиная с положительной X оси, и заканчивается в точке с углом (в радианах) angle2. Если angle2 меньше, чем angle1, angle2 будет увеличен на такое количество 2π, пока не станет больше или равен angle1.

Изображение radius (green), angle1 (red), angle2 (blue)

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

(defun pie-wedge (file)
  (with-canvas (:width 80 :height 60)
    (let ((x 0) (y 0)
          (radius 70)
          (angle1 (* (/ pi 180) 15))
          (angle2 (* (/ pi 180) 45))
)

      (translate 5 5)
      (set-rgb-fill 1 1 1)
      (move-to 0 0)
      (arc x y radius angle1 angle2)
      (fill-and-stroke)
      (save-png file)
)
)
)

Изображение

[Function]
arcn x y radius angle1 angle2 => |

То же, что и ARC, но рисует дугу по часовой стрелке. Если angle2 больше, чем angle1, angle2 будет уменьшен на такое количество 2π, пока не станет меньше или равно angle1.

(defun wiper (file)
  (with-canvas (:width 70 :height 70)
    (let ((x 0) (y 0)
          (r1 40) (r2 60)
          (angle1 0)
          (angle2 (* (/ pi 180) 90))
)

      (translate 5 5)
      (set-rgba-fill 1 1 1 0.75)
      (arc x y r1 angle1 angle2)
      (arcn x y r2 angle2 angle1)
      (fill-and-stroke)
      (save-png file)
)
)
)

Изображение

[Function]
close-subpath => |

Закрывает текущий подконтур. Если текущая точка не совпадает с начальной точкой подконтура, добавляет прямую линию соединяющую данные точки.

Подконтуры с совпадающими начальной и конечной точками не то же, что закрытые подконтуры. Различие важно при рисовании:

ИзображениеИзображение
Open subpath Closed subpath

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

[Function]
stroke-to-paths => |

Sets the current active paths to the paths that would result from outlining a STROKE operation FIXME.

[Function]
rectangle x y width height => |

Создает подконтур подпрямоугольника с заданной шириной и высотой и нижним левым углом в точке (x, y). Эквивалентно коду:

(move-to x y)
(line-to (+ x width) y)
(line-to (+ x width) (+ y height))
(line-to x (+ y height))
(close-subpath)
[Function]
rounded-rectangle x y width height rx ry => |

То же, что и RECTANGLE, но скругляет углы прямоугольника по оси X на радиус rx, по оси Y на радиус ry.

[Function]
centered-ellipse-path x y rx ry

Добавляет закрытый подконтур, отрисовывающий эллипс с центром в точке (x, y) по оси X с радиусом rc, по оси Y с радиусом ry.

[Function]
centered-circle-path x y radius => |

Добавляет закрытый подконтур, отрисовывающий круг с центром в точке (x, y) с радиусом radius. Эквивалентно коду:

(centered-ellipse-path x y radius radius)

Раскраска

После того, как контур определен, fill, stroke или обе эти операции будут использовать его для заполнения холста. После того, как эти операции выполнятся, он более не будет активным.

[Function]
fill-path => |

Заполняет текущий контур цветом заливки или градиентом. Если контур не закрыт явно с помощью CLOSE-SUBPATH, он будет неявно закрыт перед заливкой. The non-zero winding rule используется для определения, какие пространства должны быть заполнены FIXME.

[Function]
even-odd-fill => |

То же, что и FILL-PATH, но используется алгоритм определения внутренних областей "even/odd rule" FIXME.

[Function]
stroke => |

Отрисовывает линии контура. Ширина линии, цвет, стиль изгибов, стиль концов и стиль штриха и фаза определяет алгоритм отрисовки.

[Function]
fill-and-stroke => |

Заполнить текущий контур и нарисовать его линии.

[Function]
even-odd-fill-and-stroke => |

То же, что и fill-and-stroke, но используется правило четности/нечетности при определении внутренних областей FIXME.

[Function]
end-path-no-op => |

Завершает текущий контур без отрисовки. Если были определены области отсечения с помощью CLIP-PATH или EVEN-ODD-CLIP-PATH, они будут созданы данной функцией.

Text

Vecto может отрисовывать текст на холсте. Она загружает глифы фигур из TrueType шрифтов с помощью ZPB-TTF.

[Function]
get-font font-file => font-loader

Создает и возвращает объект ZPB-TTF, являющийся загрузчиком шрифта из файла. Любой загрузчик шрифта, созданный таким образом, будет ватоматически закрыт в конце формы WITH-CANVAS.

[Function]
set-font font-loader size => |

Устанавливает в текущий шрифт шрифт, свзяанный с загрузчиком шрифтом, с заданным размером.

Первым аргументом должен быть ZPB-TTF загрузчик шрифтов, созданный с помощью GET-FONT. Только загрузчики шрифтов созданные с помощью GET-FONT будут автоматчески закрыты в конце формы WITH-CANVAS.

[Function]
set-character-spacing spacing => |

Модифицирует размер интервала между символами при отрисовке текста с помощью DRAW-STRING, и связанных функций.

Обычно, интервал между символами для отрисовываемого текста берется прямо из характеристик шрифта: ширины и кернинга. SET-CHARACTER-SPACING может быть использована для выравнивания интервала, например, spacing равный 2.0d0 увеличивает интервал вдвое, тогда как 0.5d0 уменьшает его вдвое.

[Special variable]

*default-character-spacing*

Переменная для хранения значения по-умолчанию для интервала между символами, при отрисовке текста с помощью функциями DRAW-STRING и связанными с ней. Первоначальное значение 1.0d0.

Изменение этой переменной будет применено при следующем вызове формы WITH-CANVAS. Для получения результата в текущей форме WITH-CANVAS используйте SET-CHARACTER-SPACING.

[Function]
draw-string x y string => |

Отрисовки строки на холсте текущим шрифтом. Вершина глифа первого символа строки будет находится в точке x и линия строки будет иметь значение y. Текст будет залит текущим цветом.

Строка может быть вектором символом (в CL строка так называется) или вектор содержащий символы, Юникодные символы или все вместе. Например, #(#\L #\a #\m #\b #\d #\a #\= #x3BB) является корректным аргументом для DRAW-STRING.

Горизонтальный интервал между символами определяется свойствами шрифта, и умножается на текущий множитель. По-умолчанию множитель равен 1.0d0. SET-CHARACTER-SPACING может использоваться для регулировки этого интервала.

[Function]
string-paths x y string => |

То же, что и DRAW-STRING, но вместо рисования текста, добавляет подконтур для создания строки глифов в текущем состоянии. Может быть использовано для отрисовки линий, заливки или области отсечения.

[Function]
draw-centered-string x y string => |

Отрисовывает строку на холсте текущим шрифтом. Горизонтальный центр строки устанавливается в точку x, и базовая линия строки имеет координату y.

[Function]
centered-string-paths x y string => |

То же, что и DRAW-CENTERED-STRING, но добавляет подконтур, вместо рисования. Смотрите также STRING-PATHS.

[Function]
string-bounding-box string size loader => #(xmin ymin xmax ymax)

Вычисляет ограничивающую рамку для строки для загрузчика шрифта с указанным размером шрифта.

Дополнительно

[Constant]
+kappa+ => 0.5522847498307936d0.

Данная константа полезна для рисования частей круга.

Ссылки

  Adobe Systems Inc., [[http://www.adobe.com/devnet/pdf/pdf_reference.html|PDF Reference, Sixth Edition, Version 1.7]]
Lawrence Kesteloot, [[http://www.teamten.com/lawrence/graphics/premultiplication/|Alpha Premultiplication]]
Dr. Thomas Sederberg, [[http://www.tsplines.com/resources/class_notes/Bezier_curves.pdf|Bézier curves]]
Alvy Ray Smith, [[http://alvyray.com/Memos/MemosMicrosoft.htm#ImageCompositing|Image Compositing Fundamentals]]
G. Adam Stanislav, [[http://www.whizkidtech.redprince.net/bezier/circle/|Drawing a circle with Bézier curves]]
Alexander Thomas, [[http://www.dr-lex.be/random/matrix_inv.html|The Inverse and Determinants of 2x2 and 3x3 Matrices]]
Wikipedia, [[http://en.wikipedia.org/wiki/B%C3%A9zier_curve|Bézier curve ]]

Благодарности

Большое спасибо Бену Дину за разрешение адаптировать его код из библиотеки для рисования дуг.

Раян Дэвис помог исправить мою адаптацию кода рисования дуг.

Обратная связь

Если у вас есть какие-либо вопросы, комметарии, проблемы касаемые Vecto, пожалуйста, пишите Zach Beane

@2009-2013 lisper.ru