Python para Desenvolvedores

2ª edição, revisada e ampliada

Capítulo 36: SVG


SVG (Scalable Vector Graphics) é um formato aberto, baseado no XML, que descreve imagens vetoriais, na forma de estruturas compostas por instruções de alto nível que representam primitivas geométricas. O formato foi proposto pelo W3C (World Wide Web Consortium), a entidade que define os padrões vigentes na Internet, como o HTML e o próprio XML.

SVG

Arquivos SVG podem armazenar vários tipos de informações vetoriais, incluindo polígonos básicos, que são representados por linhas que delimitam uma área fechada, tais como retângulos, elipses e outras formas simples. Além disso, ele também suporta caminhos (paths), que são figuras, com preenchimento ou não, compostas por linhas e/ou curvas definidas por pontos, que são codificados através de comandos de um caractere (“L” significa “Line To”, por exemplo) e um par de coordenadas X e Y, o que gera um código muito compacto.

Texto unicode pode ser incluído em um arquivo SVG, com efeitos visuais, e a especificação inclui tratamento de texto bidirecional, vertical e seguindo caminhos curvos. O texto pode ser formatadas com fontes de texto externas, mas para amenizar o problema do texto não ser apresentado corretamente em sistemas diferentes, existe uma fonte interna, que está sempre disponível.

As figuras geométricas, caminhos e texto podem ser usados como contornos, internos ou externos, que pode usar três tipos de preenchimento:

  • Cores sólidas, que podem ser opacas ou com transparência.
  • Gradientes, que podem ser lineares ou radiais.
  • Padrões, que são imagens bitmap ou vetoriais que se repetem ao longo do objeto.

Tantos os gradientes quantos os padrões podem ser animados.

O SVG também permite que o autor inclua metadados com informações a respeito da imagem, tais como título, descrição e outros, com o objetivo de facilitar a catalogação, indexação e recuperação dos arquivos.

Todos os componentes de um arquivo SVG pode ser lidos e alterados usando scripts da mesma forma que o HTML, tendo como padrão a linguagem ECMAScript. A especificação também prevê tratamento de eventos de mouse e teclado, o que, junto com hyperlinks, permite adicionar interatividade aos gráficos.

O formato também suporta animação através do ECMAScript, que pode transformar os elementos da imagem e temporizar o movimento. Isso também poder ser feito através de recursos próprios do SVG, usando tags.

Para o SVG, filtros são conjuntos de operações gráficas que são aplicadas a um determinado gráfico vetorial, para produzir uma imagem matricial com o resultado. Tais operações gráficas são chamadas primitivas de filtro, que geralmente realizam uma forma de processamento de imagem, como, por exemplo, o efeito Gaussian Blur, e por isso, geram um bitmap com transparência (padrão RGBA) como saída, que é regerado se necessário. O resultado de uma primitiva pode ser usado como entrada para outra primitiva, permitindo a concatenação de várias para gerar o efeito desejado.

SVGFig

Os arquivos SVG podem manipulados através de bibliotecas XML, como o ElementTree, mas é mais produtivo usar componentes que já projetados com essa finalidade. O SVGFig é um módulo para SVG com muitos recursos prontos. O módulo permite tanto usar as primitivas de desenho do SVG diretamente, como também rotinas próprias de alto nível.

Exemplo (usando primitivas do SVG):

In [3]:
# Importa SVGFig
from svgfig import *

cores = ['#dddddd', '#306090', '#609030', '#906030']

# Um retângulo usando SVG
# x, y  -> posição do canto superior esquerdo
# width, height -> tamanho
# fill -> cor do preenchimento
# opacity -> opacidade (1.0 = 100%)
# stroke_width -> largura da linha (em pontos)
q1 = SVG('rect', x=0, y=0, width=100, height=100,
    fill=cores[0],  opacity='1.0', stroke_width='0.2pt')

# Primeiro círculo
# cx, cy -> posição do centro
# r -> raio
c1 = SVG('circle', cx=35, cy=65, r=30,
    fill=cores[1],  opacity='0.5', stroke_width='0.2pt')

# Segundo círculo
c2 = SVG('circle', cx=65, cy=65, r=30,
    fill=cores[2],  opacity='0.5', stroke_width='0.2pt')

# Terceiro círculo
c3 = SVG('circle', cx=50, cy=35, r=30,
    fill=cores[3],  opacity='0.5', stroke_width='0.2pt')

# Criando um grupo com as figuras
g = SVG('g', q1, c1, c2, c3)

# Salvando
g.save("tmp.svg")

#Imprimindo o resultado
print open('tmp.svg').read()
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg style="stroke-linejoin:round; stroke:black; stroke-width:0.5pt; text-anchor:middle; fill:none" xmlns="http://www.w3.org/2000/svg" font-family="Helvetica, Arial, FreeSans, Sans, sans, sans-serif" height="400px" width="400px" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">

<g>

<rect opacity="1.0" height="100" width="100" y="0" x="0" stroke-width="0.2pt" fill="#dddddd" />

<circle opacity="0.5" stroke-width="0.2pt" cy="65" cx="35" r="30" fill="#306090" />

<circle opacity="0.5" stroke-width="0.2pt" cy="65" cx="65" r="30" fill="#609030" />

<circle opacity="0.5" stroke-width="0.2pt" cy="35" cx="50" r="30" fill="#906030" />

</g>

</svg>


SVG Circles

Exemplo (com rotinas do SVGFig):

In [4]:
from math import sin, cos, pi
from svgfig import *

# Cria uma curva para t = seno(2t) / 2 + cosseno(3t)
# de -2Pi a 2 Pi, da cor #ccbbaa
curva = Curve('t, 0.5 * sin(2*t) + cos(3*t)',
    -2*pi, 2*pi, stroke='#ccbbaa')

# Gera um gráfico com eixos
# X (-2Pi a 2Pi) e Y (-2 a 2) com a curva
grafico = Plot(-2*pi, 2*pi, -2, 2, curva)

# Cria um objeto SVG
svg = grafico.SVG()

# Salva em um arquivo
svg.save("tmp2.svg")

SVG Curves

O SVGFig tem várias primitivas de desenho implementadas na forma de funções, incluindo caminhos (Path()), linhas (Line()) e texto (Text()).

In [1]:
 
Out[1]: