O editor de imagens vetoriais Inkscape permite o uso do Python como linguagem script, para a criação de extensões. O aplicativo utiliza o SVG como formato nativo e implementa vários recursos previstos no padrão.
As extensões para o Inkscape servem principalmente para a implementação de filtros e efeitos. Enquanto outros aplicativos (como o Blender) apresentam uma API na forma de módulos para o interpretador, o Inkscape passa argumentos pela linha de comando e transfere informações pela entrada e saída padrão do sistema operacional, de forma similar aos utilitários de tratamento de texto encontrados em sistemas UNIX. Com isso, a extensão tem acesso apenas aos elementos que fazem parte do documento, e não a interface gráfica do aplicativo. Qualquer interação com o usuário durante a execução fica por conta da extensão.
A criação e manipulação das estruturas de dados é feita usando XML, como prevê a especificação do formato SVG, permitindo com isso o uso de módulos como o ElementTree.
Para simplificar o processo, o Inkscape provê o módulo chamado inkex, que define estruturas básicas para extensões. Com esse módulo, novas extensões podem ser criadas por herança a partir de uma classe chamada Effect.
Exemplo (randomtext.py):
import random
import inkex
import simplestyle
class RandomText(inkex.Effect):
"""
Repete um texto aleatoriamente dentro de uma área.
"""
def __init__(self):
# Evoca a inicialização da superclasse
inkex.Effect.__init__(self)
# Adiciona um parâmetro para ser recebido do Inkscape
self.OptionParser.add_option('-t', '--texto',
action = 'store', type = 'string',
dest = 'texto', default = 'Python',
help = 'Texto para ser randomizado')
self.OptionParser.add_option('-q', '--quantidade',
action='store', type='int',
dest='quantidade', default=20,
help='Quantidade de vezes que o texto irá aparecer')
self.OptionParser.add_option('-l', '--largura',
action='store', type='int',
dest='largura', default=1000,
help='Largura da área')
self.OptionParser.add_option('-c', '--altura',
action='store', type='int',
dest='altura', default=1000,
help='Altura da área')
def effect(self):
# Pega as variáveis que foram passadas como
# opções de linha de comando pelo Inkscape
texto = self.options.texto
quantidade = self.options.quantidade
largura = self.options.largura
altura = self.options.altura
# Raiz do SVG
svg = self.document.getroot()
# Altura e largura do documento
doc_largura = inkex.unittouu(svg.attrib['width'])
doc_altura = inkex.unittouu(svg.attrib['height'])
# Cria uma camada no documento
camada = inkex.etree.SubElement(svg, 'g')
camada.set(inkex.addNS('label', 'inkscape'), 'randomtext')
camada.set(inkex.addNS('groupmode', 'inkscape'), 'camada')
for i in xrange(quantidade):
# Cria um elemento para o texto
xmltexto = inkex.etree.Element(inkex.addNS('text','svg'))
xmltexto.text = texto
# Posiciona o elemento no documento
x = random.randint(0, largura) + (doc_largura - largura) / 2
xmltexto.set('x', str(x))
y = random.randint(0, altura) + (doc_altura - altura) / 2
xmltexto.set('y', str(y))
# Centraliza na vertical e na horizontal
# e muda a cor de preenchimento usando CSS
c = random.randint(100, 255)
style = {'text-align' : 'center',
'text-anchor': 'middle',
'fill': '#%02x%02x%02x' % (c, c - 30, c - 60)}
xmltexto.set('style', simplestyle.formatStyle(style))
# Coloca o texto na camada
camada.append(xmltexto)
if __name__ == '__main__':
rt = RandomText()
rt.affect()
Para que o Inkscape reconheça a nova extensão, é necessário criar um arquivo XML com a configuração, que informa ao aplicativo os módulos e os parâmetros usados pela extensão, incluindo os tipos, limites e valores padrão desses parâmetros, para que ele possa interagir com o usuário através de uma caixa de dialogo antes da execução para obter os valores desejados. Os parâmetros são passados como argumentos na linha de comando quando o script é executado.
Arquivo de configuração (randomtext.inx):
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<_name>RandomText</_name>
<id>org.ekips.filter.randomtext</id>
<dependency type="executable" location="extensions">randomtext.py</dependency>
<dependency type="executable" location="extensions">inkex.py</dependency>
<param name="texto" type="string" _gui-text="Texto">Python</param>
<param name="quantidade" type="int" min="1" max="500" _gui-text="Quantidade">20</param>
<param name="largura" type="int" min="1" max="10000" _gui-text="Largura">1000</param>
<param name="altura" type="int" min="1" max="10000" _gui-text="Altura">1000</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu _name="Render"/>
</effects-menu>
</effect>
<script>
<command reldir="extensions" interpreter="python">randomtext.py</command>
</script>
</inkscape-extension>
Janela com os parâmetros da extensão:
Exemplo de saída (quantidade igual a 100, largura igual a 600 e altura igual a 200):
Tanto o programa quanto o arquivo de configuração precisam ficar na pasta de extensões (share\extensions
, dentro da pasta de instalação, para a versão Windows) para que sejam encontrados pelo aplicativo e o nome do arquivo de configuração precisa ter extensão .inx
.