Conteúdo


Adicione seus próprios recursos GIMP

Mergulhe na base de código do GNU Image Manipulation Program

Comments

Por que o GIMP?

Uma das razões mais atraentes para usar software grátis ou livre é que ele oferece a oportunidade para o usuário do produto de adicionar quaisquer recursos que desejar ou precisar. Mas a capacidade de adicionar recursos é restringida pelo tamanho e complexidade de um projeto e pela natureza da documentação disponível. Portanto, apesar de o GIMP ser um dos projetos de software livre mais conhecidos e bem-sucedidos, sua enorme base de código pode ser intimidadora.

Para acompanhar, você deverá estar familiarizado com a linguagem de programação C. Você também deverá conhecer ou estar preparado para aprender sobre a ferramenta de controle de versão Git. O exemplo neste artigo foi criado usando o GIMP V2.7 em um ambiente Linux® (note que V2.7 é uma ramificação de desenvolvimento, e não um release estável). A versão do Mandriva Linux lançada na primavera de 2009 foi usada neste artigo, mas qualquer versão do Linux deverá funcionar (consulte Recursos).

Você criará uma ferramenta com base em uma ferramenta de pintura existente. A ferramenta criada neste artigo é puramente para fins educativos. Para que se torne um projeto real a ser usado como parte da distribuição do GIMP, ela teria que ser cuidadosa e minuciosamente examinada pelos principais desenvolvedores GIMP e pelo arquiteto de UI.

A primeira etapa para trabalhar com o GIMP é compilá-lo. Apesar de ser trivial olhar o código simplesmente descompactando um tarball fonte, e ainda mais fácil usar a interface web do Git para o repositório de código, pode ser traiçoeiro realizar sua compilação.

Considerando o tamanho do código fonte, o GIMP é bem mantido e consistente para compilar. No entanto, você terá que lidar com o problema das dependências necessárias. Ao executar software como o GIMP, muitas bibliotecas são instaladas de forma transparente em seu sistema. Quando quiser compilar este software, mais informações, além dos binários das bibliotecas, são necessárias. A maioria das distribuições do Linux empacotam estas dependências separadamente dos pacotes principais. Além das bibliotecas, você também precisará do compilador em si e das cadeias de ferramentas associadas. Nas distribuições mais populares do Linux, você só precisará digitar uns poucos comandos para ter tudo pronto.

Para o código fonte do GIMP propriamente dito, é preciso obter uma das versões de desenvolvimento do Git. É preferível obter uma árvore Git, mesmo se for trabalhar no código da versão estável. Isto permite controlar facilmente suas próprias alterações ao código. O Git é um software de controle de versão descentralizado, que pode ser usado para manter o código GIMP no repositório principal. Ele foi projetado para ser usado a partir da linha de comandos, apesar de existirem interfaces gráficas.

Obtendo o código fonte do GIMP

Para recuperar a última versão de desenvolvimento, simplesmente digite git clone git://git.gnome.org/gimp na linha de comandos. Depois de alguns minutos, você terá o código completo do GIMP. As coisas são bem organizadas, tornando relativamente simples encontrar o caminho entre mais de 3.000 arquivos baixados.

Uma observação sobre o uso do Git

Ao fazer alterações, não é preciso se preocupar com a perda de algum de seus arquivos originais, ou mesmo suas alterações, caso decida preservá-los para suas personalizações, graças ao sistema Git. Por exemplo, para redefinir qualquer arquivo para a forma como ele está no repositório do GIMP, simplesmente digite git checkout <filename>.

De qualquer forma, você precisará se familiarizar com o Git, mesmo que não planeje contribuir com seu código. Ele pode tornar sua vida muito mais fácil, mesmo que o esteja usando somente para controlar as alterações que tenha feito ao código base. Por exemplo, a qualquer momento, é possível ver todas as alterações que foram realizadas na base do código simplesmente digitando git diff.

Usar o Git adequadamente permite criar ramificações locais, onde é possível desenvolver diferentes recursos e, a qualquer momento, atualizá-los com as alterações no GIMP.

Construindo o GIMP

Para obter uma compilação da ramificação de desenvolvimento do GIMP — o master do Git — você precisará das versões recentes das bibliotecas mostradas na Listagem 1 e seus cabeçalhos instalados. Esses cabeçalhos geralmente vêm em pacotes do Linux chamados *-dev ou *-devel.

Antes de iniciar, seria bom olhar o arquivo HACKING, que acompanha os arquivos fonte do GIMP, e especifica as regras para o desenvolvimento do projeto.

Listagem 1. Bibliotecas que deverão ser obtidas para compilar o master atual do Git
glib 2.24.0
gtk 2.20.0
babl, 0.1.2
gegl, 0.1.2
libpng 1.2.34
cairo 1.6.0
pango 1.20.1
fontconfig 2.2.0
gtkdoc 1.0

Além dessas bibliotecas obrigatórias, você precisa das seguintes bibliotecas extras (consulte a Listagem 2). Se elas não forem encontradas, você terá funcionalidades ausentes e terá que passar opções para o sistema de compilação para ignorá-las. Por exemplo, será preciso chamar autogen.sh com autogen.sh --prefix=<prefix> --without-libpng se você não tiver o pacote de desenvolvimento para libpng instalado.

Listagem 2. Outras bibliotecas importantes
pygtk 2.10.4
poppler0.4.1
libcurl 7.15.1
dbus_glib 0.70
libhal 0.5.7
exif  0.6.15
lcms 1.16
libpng 1.2.37

Assegurando-se de que as bibliotecas em seu sistema estão atualizadas

Para as bibliotecas já atualizadas em seu sistema, o sistema package-managing de sua distribuição do Linux pode buscar automaticamente as bibliotecas necessárias e seus pacotes devel.

No Ubuntu e no Debian, simplesmente digite sudo apt-get build-dep gimp.

No Mandriva Linux, é possível usar a opção --buildrequires do URPMI: urpmi --buildrequires gimp. Será preciso primeiro configurar um repositório de rpm fonte.

Para OpenSuSE, é bom verificar a documentação do comando zypper.

No Fedora, Redhat, CentOS e SuSe, e na maioria das outras distribuições, você terá que instalar os pacotes -devel manualmente. Não se preocupe se esquecer de algum deles; o sistema de compilação parará e pedirá por ele. Uma mensagem enganadora é exibida neste caso, que dirá que a biblioteca x está ausente. No entanto, uma rápida verificação revelará que você tem a biblioteca x instalada em seu sistema. A forma entre distribuições para verificar versões de bibliotecas é o comando pkg-config. Por exemplo, pkg-config --modversion gtk+-2.0 exibirá a versão instalada de GTK+ V2.x.

Se o sistema de compilação reclamar sobre uma versão antiga, você precisará de uma nova no prefixo de seu novo GIMP. Se disser que a biblioteca está ausente, é mais provável que estejam faltando os arquivos de cabeçalho C, que o software usa para que as bibliotecas possam ser compiladas. Estes arquivos de cabeçalho estão geralmente em pacotes separados — aqueles terminados em -dev ou -devel, de acordo com sua distribuição. Ou seja, mesmo se tiver o GTK V2.20 instalado em seu sistema, é preciso instalar o pacote gtk2-devel.

Bibliotecas desatualizadas ou ausentes no repositório de sua distribuição

Nem todas as bibliotecas mencionadas acima estarão atualizadas para que você compile o GIMP em sua distribuição do Linux. Isto é especialmente verdade se você tentar compilar o master do GIMP — a versão de desenvolvimento. Mas também poderá ocorrer em sistemas mais antigos ao tentar compilar um GIMP estável. Para compilar o GIMP de desenvolvimento, você terá tipicamente que compilar pelo menos a biblioteca GEneric Graphics Library (GEGL) do Git.

As bibliotecas desatualizadas ou ausentes deverão ser buscadas do último tarball estável para cada uma delas. Normalmente, a primeira ocorrência de download da biblioteca x ao buscar na Web o levará à página de download de cada biblioteca. Talvez você prefira buscar a versão do Git, em vez do tarball, o que é uma prática aceitável, mas é melhor ser conservador e buscar ramificações estáveis para o Git de cada biblioteca, e não usar versões instáveis.

Uma exceção é a biblioteca GEGL, que exige que você busque a ramificação master do Git (instável) para compilar o master do GIMP, em vez da última ramificação estável. O GEGL está em processo de substituição da composição do núcleo e operações de imagem no GIMP propriamente dito. Recupere seu código com git clone git://git.gnome.org/gegl.

Para cada biblioteca que precisar instalar desta forma (e para o próprio GIMP), será preciso ter cuidado para não sobrescrever a biblioteca que veio instalada em sua distribuição. Para evitar isto, você deverá compilá-las em outro prefixo de diretório. Normalmente, eu uso o prefixo /opt. Outras formas de conseguir isto, além de passar a opção --prefix para o script configure (ou autogen.sh), envolve criar as seguintes variáveis, como mostra a Listagem 3.

Listagem 3. Variáveis para compilação
PREFIX=/opt
export PATH=$PREFIX/bin:$PATH
export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH
export ACLOCAL_FLAGS="-I $PREFIX/share/aclocal"

Antes de instalar a primeira biblioteca desta forma, assegure-se de que o diretório /opt/share/aclocal existe; se não, crie-o.

A maioria dos componentes necessários usa o sistema make e pode ser compilada e instalada em seu sistema alternando para o diretório do código fonte descompactado, como mostra a Listagem 4.

Listagem 4. Compilando e instalando componentes usando make
./configure --prefix=<xxx>
make
sudo make install

Para as bibliotecas que você buscou com o Git, substitua o primeiro comando na Listagem 4, /configure, por ./autogen.sh --prefix=<xxx>. Além disso, se estiver compilando GTK+, inclua a opção --with-xinput=yes na linha de comandos autogen ou configure. Isto permitirá que tablets e outros dispositivos sensíveis à pressão funcionem com o GIMP.

Compilando o GIMP

Uma vez que os pré-requisitos estejam no lugar, compilar o GIMP é simples e direto. Defina as mesmas variáveis de ambiente da Listagem 4 para que o GIMP possa buscar as bibliotecas mais novas no prefixo diferente que você escolheu e faça com que o GIMP seja compilado também naquele prefixo. Isto evitará conflito com GIMP estável propriamente dito, instalado pelo sistema (consulte a Listagem 5).

Listagem 5. Definindo variáveis de ambiente
PREFIX=/opt
export PATH=$PREFIX/bin:$PATH
export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH
export ACLOCAL_FLAGS="-I $PREFIX/share/aclocal"

Faça um script com essas configurações e execute-o com o comando shell fonte. Você precisará definir estas variáveis a cada vez que compilar o GIMP. A seguir, alterne para o diretório base fonte do GIMP e digite o código na Listagem 6.

Listagem 6. Instalando o código fonte do GIMP com make
./autogen.sh --prefix=<xxx>
make
sudo make install

Se houver qualquer mensagem de erro sobre bibliotecas ausentes, faça como descrito na seção "Bibliotecas desatualizadas ou ausentes no repositório de sua distribuição".

Olhando o código fonte

Agora que você compilou o GIMP com sucesso, é hora de ver o que há de novo dentro do código fonte do GIMP.

Entre os recursos do programa que deverá verificar está a capacidade de marcar recursos, como pincéis, paletas, gradientes, grupos de camadas, edição de texto na tela e a nova dinâmica de pintura. Cada um desses poderia facilmente encher um capítulo em um livro sobre o GIMP. Como eles estão sendo ativamente desenvolvidos, tenha em mente que, se escolher modificar essas seções, será melhor se colaborar de perto com os desenvolvedores, ou suas alterações serão inúteis posteriormente.

A árvore fonte

O fonte do GIMP começa com 29 diretórios, sete dos quais são somente para os arquivos de tradução dos outros componentes (os diretórios po.*). Nove são para bibliotecas modularizadas, que contêm funções e constantes específicas que podem ser usadas de dentro do GIMP propriamente dito ou a partir de plug-ins escritos em C. Outros diretórios dignos de nota incluem o diretório de plug-ins, onde reside o código para todos os plug-ins que acompanham o GIMP, incluindo o esquema (script-fu) e as extensões do Python para escrever plug-in e scripts.

E, finalmente, todo o código do aplicativo em si está contido dentro do diretório app. Existem alguns arquivos C aqui, juntamente com 20 diretórios onde o aplicativo em si é distribuído. Alguns dos nomes são descritivos do que o código interno deverá fazer, como dialogs ou xcf, outros são mais gerais, como core, base e actions.

Encontrando seu caminho no código fonte

Como um grande projeto, cada recurso no GIMP é bem separado, para que o código que lida com o mesmo conjunto de recursos esteja agrupado. A maioria dos arquivos C é armazenada no diretório /app e é vinculada no único binário executável do GIMP quando o projeto é compilado. Existem mais de 900 arquivos C aqui e quase o mesmo número de arquivos de cabeçalho (.h), portanto prepare-se para pesquisar bastante quando procurar onde um recurso está codificado.

Uma das melhores formas de encontrar onde reside o código para um recurso que você viu no programa é usar o comando grep. O grep é um utilitário padrão de linha de comandos do UNIX® para pesquisar por um padrão de texto dentro de um ou vários arquivos. Uma forma segura de procurar por um recurso é pesquisar por qualquer texto que ele apresente na UI propriamente dita. É claro, será preciso executar o GIMP em inglês para isso, ou todo o texto mostrado na tela estará nos arquivos de tradução de cadeia de caractere, no diretório po/ (fora da árvore do aplicativo).

Suponha que deseja encontrar o código responsável por alternar uma janela GIMP para o modo de tela cheia. Primeiro, você verifica que a dica de ferramenta para ele é Toggle fullscreen view (no menu View do GIMP). Alternando para o diretório app, é possível digitar grep -i "toggle fullscreen view" ‛find -name "*c" ‛.

O comutador -i diz ao grep para diferenciar maiúsculas e minúsculas e o subcomando ‛find -name "*c" (note que ele está envolto em aspas para trás, o que é essencial, pois o comando não funcionará com outros tipos de aspas) retorna uma lista de todos os arquivos C na árvore de diretórios na qual está pesquisando. Portanto, o grep executa em todos os arquivos C procurando pelo padrão de texto que foi fornecido. A resposta seria a seguinte:

./actions/view-actions.c:    NC_("view-action", "Toggle fullscreen view"),

Para olhar este arquivo, sugiro usar o comando less. Se quiser olhar dentro deste arquivo mais detalhadamente, use o editor de texto de sua escolha (consulte a Listagem 7).

Listagem 7. Olhando dentro do arquivo view-actions.c
  { "view-fullscreen", GTK_STOCK_FULLSCREEN,
    NC_("view-action", "Fullscr_een"), "F11",
    NC_("view-action", "Toggle fullscreen view"),
    G_CALLBACK (view_fullscreen_cmd_callback),
    FALSE,
    GIMP_HELP_VIEW_FULLSCREEN },

Portanto, mesmo sem entender tudo o que este arquivo faz, você pode antecipar a próxima etapa. A única coisa que a entrada action faz é associá-la com uma função chamada view_fullscreen_cmd_callback e nada mais. Portanto, seu próximo passo é executar o grep novamente. Até onde você sabe, esta função poderia estar em qualquer lugar na árvore:

grep -i  "view_fullscreen_cmd_callback" ‛find -name "*c" ‛

Isto retorna duas ocorrências: Uma delas é a entrada que você acabou de ver no arquivo actions.c propriamente dito; a outra está dentro do arquivo ./actions/view-commands.c. Ao olhar dentro daquele arquivo, finalmente você verá algum código. Há uma função C que verifica se uma janela existe, recupera a imagem ativa e chama uma função de nome gimp_image_window_set_fullscreen. Você adivinhou; esse é nosso próximo alvo no grep:

grep -i  gimp_image_window_set_fullscreen   ‛find -name "*c" ‛

Isto nos leva diretamente ao arquivo app/display/gimpimagewindow.c, mostrado na Listagem 8. Ao olhar o conteúdo deste arquivo, você verá o que esta função faz. Isso acaba sendo bem simples: apenas faça uma chamada para a função GTK+ para maximizar a janela.

Listagem 8. app/display/gimpimagewindow.c
gimp_image_window_set_fullscreen (GimpImageWindow *window,
                                  gboolean         fullscreen)
{
  g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));

  if (fullscreen != gimp_image_window_get_fullscreen (window))
    {
      if (fullscreen)
        gtk_window_fullscreen (GTK_WINDOW (window));
      else
        gtk_window_unfullscreen (GTK_WINDOW (window));
    }
}

Apesar de a função do maximizador em si ser bastante simples, ao visualizar o conteúdo deste arquivo, é possível ter uma boa noção do comportamento interno do GIMP. O código responsável por exibir a janela superior e manter seus atributos está presente neste arquivo. Se estiver usando a árvore do GIMP V2.7, verá bastante código recém-escrito usado para gerenciar os diálogos acopláveis quando o GIMP está no novo modo de janela única.

Neste ponto, também é possível ter uma boa ideia do que as ações e os arquivos de comando nas ações fazem. Não é preciso entendê-los completamente para saber que criam comandos que podem ser chamados como ações pelos usuários. As ações em si são eficientes ainda mais, agregando meta-informações, como dicas de ferramenta, texto de exibição, dicas de tradução etc. Quando uma ação é nomeada, ela pode ser usada diretamente a partir de um arquivo XML para ser adicionada a um menu do aplicativo, por exemplo. Os arquivos XML que criam os menus a partir das ações no diretório app/actions estão todos no diretório menu no diretório root do projeto. Reordenar os menus do GIMP é simplesmente uma questão de editar um arquivo XML.

Modificando o código fonte do GIMP

Agora que você tem uma ideia de como encontrar recursos dentro da árvore fonte, é hora de fazer algumas alterações. Neste estágio, você deveria tentar alguma alteração menor só para ver como funciona. Vamos começar desativando a funcionalidade de tela cheia comentando uma chamada de função acima e recompilando o GIMP.

Para ver isso, basta abrir o arquivo app/display/gimpimagewindow.c acima para edição e, na primeira linha dentro da função gimp_image_window_set_fullscreen, adicionar uma instrução return;. Recompile seu aplicativo GIMP digitando make. Não há necessidade de executar novamente autogen.sh. Também é possível executar o arquivo binário resultante gimp-2.7 no diretório app, em vez de reinstalá-lo. Esta versão do GIMP não terá o recurso de tela cheia.

Programação orientada a objetos no C

O C não é comumente considerado como uma linguagem orientada a objetos (OO), mas OO é mais uma forma de construir aplicativos do que é intrínseca a linguagens. Assim como é possível codificar aplicativos não OO em linguagens que o forçam a usar uma sintaxe de classe/instância, também é possível escrever código OO sem as comodidades de sintaxe fornecidas por linguagens de nível mais alto.

Este é o caso com o GIMP: Ele tem como base a estrutura GObject, que permite que o código C seja escrito de uma forma OO e comportar-se de forma semelhante à OO em tempo de execução. A desvantagem é que ele requer algum código padrão para criar novas classes e manipular objetos. Por outro lado, simplesmente funciona.

Um dos ganhos de ter bibliotecas OO escritas em C é que você pode ter vinculações de linguagem para outras linguagens, como Python, Ruby, a linguagem de programação Java, etc. Bibliotecas estreitamente vinculadas ao GIMP, como GTK+, GEGL e muitas outras, também usam o sistema GObject.

Criando uma nova ferramenta

Agora, vamos fazer uma mudança de verdade no programa. No exemplo deste artigo, você criará uma ferramenta de pintura que poderá ser selecionada a partir da caixa de ferramentas. Tenha em mente que, antes de criar uma nova ferramenta, é preciso revisar a funcionalidade que já existe no programa.

Entre as possíveis combinações de dinâmica de pintura, pincéis animados, modos de pintura e ferramentas existentes, muitas combinações podem ser obtidas. Uma coisa que não é possível atualmente, por exemplo, é fazer com que uma única pincelada varie de cor de forma radial para que o centro do pincel seja exibido em uma cor e a parte externa da máscara do pincel use outra cor. A seleção de cor para a pincelada seguiria o gradiente ativo, pois ela funciona para a opção de pintura "cor do gradiente".

Encontrando o que alterar

O primeiro passo é identificar quais arquivos você precisará copiar, modificar e adicionar ao sistema de compilação para que o aplicativo obtenha uma ferramenta extra para pintura que tenha o comportamento descrito acima. O primeiro local a procurar é o diretório app/tools, nos arquivos gimppaintbrushtool.h e gimppaintbrushtool.c.

Para nossa decepção, eles são somente pequenos arquivos com o que é, em sua maioria, código padrão para criar a ferramenta como uma classe GObject. Voltando à linha de comandos, no diretório app, é possível realizar um grep por paintbrush para verificar se há algum outro lugar que possa conter o código relevante.

Desta vez, uma lista um tanto maior, contendo vários arquivos e alguns pontos dentro de cada arquivo, é retornada. A boa notícia é que você obteve resultados. A notícia não tão boa é que, como pretende clonar a ferramenta de pintura, terá que visitar a maioria destes arquivos e seus cabeçalhos (.h) correspondentes e copiá-los ou adicionar referências a sua nova ferramenta, da mesma forma como existem referências à ferramenta de pintura atual.

Os arquivos listados ao realizar o grep são mostrados na Listagem 9.

Listagem 9. Resultados da busca com grep por paintbrush
./core/gimpbrush.c
./core/gimpcontext.c
./paint/gimp-paint.c
./paint/gimpairbrush.c
./paint/gimppaintbrush.c
./pdb/paint-tools-cmds.c
./tools/gimp-tools.c
./tools/gimppaintbrushtool.c
./widgets/gimpcursor.c

Ocorre que há outro arquivo chamado gimpaintbrush.c sem o sufixo tool. Abra-o para edição. Este parece promissor. Sua última função, _gimp_paintbrush_motion, na verdade realiza uma série de chamadas de função para recuperar uma área de buffer a ser pintada, o pincel atual a ser usado, a cor a ser aplicada a partir das opções de pintura e sistema dinâmico de pintura e preenche os pixels no buffer a ser pintado. Ele confirma a pincelada chamando gimp_brush_core_paste_canvas.

Experimentando um pouco

A melhor parte é que você só precisa ter uma familiaridade básica com o código C para entender o que está acontecendo. Os nomes grandes de funções e o sistema de objetos agora mostram seu valor. O código é fácil de entender. É possível também verificar o que algumas das chamadas de função fazem usando o grep para encontrar as funções e verificar seu código.

Agora você pode fazer alterações, somente para ver as mudanças, mesmo se utilizar apenas um modo de pintura ou opacidade particular ao pintar. Você poderia fazer isto substituindo o conteúdo da variável opacity por um número fixo antes de qualquer função a chame, por exemplo.

Fazendo as alterações relevantes

Para prosseguir, uma vez que tenha decidido que as alterações apropriadas no arquivo paintbrush podem obter o efeito desejado, deverá fazer uma cópia deste arquivo e renomeá-la. É uma boa ideia escolher um nome para a nova ferramenta ao fazer isto. Neste exemplo, você está usando gradientbrush.

Copie os arquivos app/paint/paintbrush.c e app/paint/paintbrush.h para gradientbrush.c e gradientbrush.h no mesmo diretório. Edite os arquivos e realize uma operação de substituição para que tudo que leia paintbrush, Paintbrush, PAINTBRUSH etc. seja respectivamente alterado para o novo nome, gradientbrush. É importante respeitar maiúsculas e minúsculas em qualquer instância. Isto criará uma nova classe GObject para sua ferramenta.

Para que os novos arquivos sejam compilados ao executar make, será preciso adicioná-los ao arquivo Makefile.am no diretório em que estão. Isto será suficiente para que sejam compilados e vinculados no executável do GIMP quando uma compilação for realizada.

Isto só cria o novo núcleo do GIMP, que ainda não faz nada; ele precisa ser integrado com uma nova ferramenta e registrado,

E, claro, quando tudo estiver no lugar, será preciso fazer as alterações necessárias na função de pintura em si para que realize a tarefa desejada: pintar usando um gradiente colorido radial juntamente com o pincel. (A Listagem 10 abaixo exibe o código para esta função.)

Quase todas as alterações necessárias a partir daqui envolvem a edição da maioria dos arquivos que incluam o termo paintbrush. Se for um arquivo listando todas as outras ferramentas de pintura, simplesmente copie as linhas que fazem referência a paintbrush e reescreva-as para que atuem no gradientbrush.

Note que, como nenhum ícone ou cursor de ferramenta novo foi criado neste exemplo, essas ocorrências de paintbrush foram mantidas como estavam: GIMP_STOCK_TOOL_PAINTBRUSH, GIMP_TOOL_CURSOR_PAINTBRUSH.

O código no diretório paint é responsável por realmente atualizar a imagem com as várias ferramentas. O código no diretório tools é responsável por vincular a funcionalidade de uma ferramenta, como paintbrush ou bucket-fill, à interface de uso. Ambos os diretórios têm arquivos a serem atualizados para criar a nova ferramenta.

Para adicionar uma cópia da ferramenta paintbrush ao diretório paint:

  1. Copie os arquivos gimppaintbrush.c e gimppaintbrush.h para gimpgradientbrush.*, e renomeie todas as ocorrências neles de paintbrush para gradientbrush (preservando maiúsculas e minúsculas).
  2. Em Makefile.am, adicione referências a gimpgradientbrush.h e gimpgradientbrush.c.
  3. Em gimp-paint.c, adicione a cláusula include no arquivo de cabeçalho gimpgradientbrush.h; adicione a função gimp_gradientbrush_register à listagem na função gimp_paint_init.
  4. Em paint-types.h, dd uma linha typedef juntamente com aquela usada para GimpPaintbrush.

Para adicionar uma cópia do paintbrush ao diretório tool:

  1. Copie os arquivos gimppaintbrushtool (c e h) para as versões gimpgradientbrushtool e renomeie as referências internas ao nome da nova ferramenta.
  2. Em Makefile.am, adicione referências nos novos arquivos gimpgradientbrushtool.
  3. Em gimp-tools.c, adicione a cláusula include ao arquivo de cabeçalho gimpgradientbrushtool.h. Adicione a função gimp_gradientbrush_register à listagem na função gimp_tools_init. E na função gimp_tools_register, adicione um bloco else if análogo àquele usado para o paintbrush. Adicione o paint_code_name em gimp-gradientbrush.

Isto deverá resolver. Agora, ao compilar, você deverá ter um ícone paintbrush extra disponível na caixa de ferramentas, como ilustrado na Figura 1.

Figura 1. Caixa de ferramentas do GIMP apresentando a ferramenta recém-criada
Caixa de ferramentas do GIMP apresentando a ferramenta recém-criada

Para o código em si, as alterações são um pouco maiores. A Listagem 10 mostra o código para o _gimp_gradientbrush_motion no arquivo app/paint/gimpgradientbrush.c. Este é o único local onde novo código teve que ser escrito para criar a nova ferramenta.

Listagem 10. Código para _gimp_gradientbrush_motion
void
_gimp_gradientbrush_motion (GimpPaintCore    *paint_core,
                            GimpDrawable     *drawable,
                            GimpPaintOptions *paint_options,
                            const GimpCoords *coords,
                            gdouble           opacity)
{
  GimpBrushCore            *brush_core = GIMP_BRUSH_CORE (paint_core);
  GimpContext              *context    = GIMP_CONTEXT (paint_options);
  GimpDynamics             *dynamics   = brush_core->dynamics;
  GimpImage                *image;
  GimpRGB                   gradient_color; 
  TempBuf                  *area;
  guchar                   *col;
  GimpPaintApplicationMode  paint_appl_mode;
  gdouble                   fade_point;
  gdouble                   force;
  guchar                   *colors;
  gint                      max_colors;
  gint                      x, y;
  gint                      u, v;
  guchar                   *area_data;
  GimpGradient             *gradient;
  gdouble                   cx, cy;

  image = gimp_item_get_image (GIMP_ITEM (drawable));
  fade_point = gimp_paint_options_get_fade (paint_options, image,
                                            paint_core->pixel_dist);

  opacity *= gimp_dynamics_output_get_linear_value (dynamics->opacity_output,
                                                    coords,
                                                    paint_options,
                                                    fade_point);
  if (opacity == 0.0)
    return;

  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options,
                                         coords);
  if (! area)
    return;

  paint_appl_mode = GIMP_PAINT_INCREMENTAL;;

  gradient = gimp_context_get_gradient (GIMP_CONTEXT (paint_options));
  max_colors = (gint)(sqrt(area->width * area->width +
                      area->height * area->height) / 2) + 1;
  colors = g_malloc(max_colors * MAX_CHANNELS);

  for (x = 0; x < max_colors; x++)
    {
      gimp_gradient_get_color_at (gradient, GIMP_CONTEXT (paint_options),
                          NULL, (gdouble)x / max_colors,
                          paint_options->gradient_options->gradient_reverse,
                         &gradient_color);
       col = &colors[x * MAX_CHANNELS];
       gimp_rgba_get_uchar (&gradient_color,
                            &col[RED],  
                            &col[GREEN],
                            &col[BLUE],
                            &col[ALPHA]);
    }

  area_data = temp_buf_get_data(area);
  cx = area->width / 2;
  cy = area->height / 2;
  for (x = 0; x < area->width; x++)
     for (y = 0; y < area->height; y++)
        {
           u = (gint)sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)) * MAX_CHANNELS;
           v = (x + y * area->width) * area->bytes;
           if (area->bytes >= 3)
             {
               area_data[v + RED] = colors[u + RED];
               area_data[v + GREEN] = colors[u + GREEN];
               area_data[v + BLUE] = colors[u + BLUE];
               if (area->bytes == 4)
                 area_data[v + ALPHA] = colors[u + ALPHA];
             }
          else
            {
              /* FIXME: get color value instead; */
              area_data[v] = colors[u + RED];
              if (area->bytes == 2)
                area_data[v] = colors[u + ALPHA];
            }
        }

  force = gimp_dynamics_output_get_linear_value (dynamics->force_output,
                                                    coords,
                                                    paint_options,
                                                    fade_point);

  /* finally, let the brush core paste the colored area on the canvas */
  gimp_brush_core_paste_canvas (brush_core, drawable,
                                coords,
                                MIN (opacity, GIMP_OPACITY_OPAQUE),
                                gimp_context_get_opacity (context),
                                gimp_context_get_paint_mode (context),
                                gimp_paint_options_get_brush_mode (paint_options),
                                force,
                                paint_appl_mode);
  g_free(colors);
}

A função _gimp_gradientbrush_motion é chamada para cada pincelada na ferramenta de pintura. Ela cria um buffer interno com metade do tamanho da diagonal do retângulo contendo o pincel que está sendo usado para pintar no GIMP e o preenche com as cores extraídas do gradiente ativo. A seguir, ela preenche a área com um mapeamento, que é um buffer de imagem usado para colorir a área de pintura de cada pincelada. Em vez de fazer uma chamada de função para preenchê-la com uma cor sólida, que a função original em gimppaintbrush.c fazia, a nova função passa por cada pixel, atribuindo a eles uma cor de acordo com sua distância ao centro do pincel.

Substitua o código de _gimp_gradientbrush_motion pelo código na Listagem 10. Ao compilar o GIMP com estas alterações, digite make, quando estiver pronto, digite make install as root e deverá ter uma nova ferramenta totalmente funcional no GIMP.

A Figura 2 mostra um rápido esboço feito com a nova ferramenta e o sistema dinâmico de pintura, definido para rastrear a direção da pintura, e um pincel de razão de aspecto alta.

Figura 2. Exemplo de uso da ferramenta gradientbrush
Exemplo de uso da ferramenta gradientbrush
Exemplo de uso da ferramenta gradientbrush

Você acabou de criar sua própria ferramenta para o GIMP

Antes de decidir criar uma nova ferramenta, você deverá também considerar escrever um plug-in para o GIMP. É um processo mais fácil do que fazer alterações no núcleo. No entanto, plug-ins têm funcionalidade limitada, como não permitir que o usuário interaja com a janela da imagem em si. Quaisquer visualizações ou interações com o usuário devem ser desenhadas de forma separada do aplicativo principal. Por outro lado, se você escrever um plug-in, ele poderá ser distribuído por si só, sem a necessidade de uma versão personalizada do GIMP, para que outras pessoas o usem.

Conclusão

Agora, você deve ter um entendimento sólido de como recuperar o código fonte e as dependências do GIMP e como compilar o GIMP em um sistema Linux. Por meio do exemplo do paintbrush, você aprendeu como navegar na árvore fonte e usar o grep para encontrar o código que implementa os recursos que deseja modificar. Você viu também o que é preciso para criar uma nova ferramenta para o GIMP. Talvez algum dia seu novo recurso entre para a fonte do GIMP para que milhões de usuários em todo o mundo o utilizem.


Recursos para download


Temas relacionados


Comentários

Acesse ou registre-se para adicionar e acompanhar os comentários.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre, Linux
ArticleID=504691
ArticleTitle=Adicione seus próprios recursos GIMP
publish-date=08022010