Trabalhar com Transformações em ficheiro PS | Java
Transformar um conteúdo num Documento PS
Neste artigo, veremos como realizar diferentes transformações: translação, dimensionamento, rotação e cisalhamento num percurso retangular adicionado ao PsDocument.
Dividimos um trecho de código em vários trechos: o início, o fim e cada transformação em separado. Uma transformação em PostScript é sempre realizada num estado gráfico ligado aos operadores “gsave” e “grestore”. Assim, no nosso PsDocument, existem os métodos “writeGraphicsSave()” e “writeGraphicsRestore()”. Entre estes métodos, podemos adicionar qualquer conteúdo, incluindo estados gráficos aninhados, e realizar quaisquer transformações ou recortes. Estas transformações não afetarão os estados gráficos externos, mas afetarão os estados gráficos aninhados.
Se realizarmos uma transformação sem os métodos “writeGraphicsSave()” e “writeGraphicsRestore()”, esta será realizada no estado gráfico do nível superior e todo o conteúdo em PsDocument será submetido a esta transformação.
Um algoritmo para definir qualquer transformação no conteúdo de um documento a partir do zero inclui os seguintes passos:
- Criar um fluxo de saída para o ficheiro PS resultante.
- Criar PsSaveOptions.
- Criar PsDocument com o fluxo de saída já criado e guardar as opções.
- Guardar um estado gráfico. Assim, criámos um novo estado gráfico e o estado gráfico anterior foi colocado numa pilha de estados gráficos.
- Adicione a transformação necessária: translação, escala, rotação, cisalhamento ou qualquer combinação das mesmas. No nosso código, mostramos a influência de cada componente da transformação em separado e, no final, 3 componentes de cada vez.
- Adicione o conteúdo necessário para a transformação. No nosso caso, criámos java.awt.geom.Rectangle2D e preenchemos. Criamos um retângulo antes de qualquer transformação e preenchemo-lo após cada transformação no estado gráfico atual.
- Restauramos o estado gráfico para voltar ao estado anterior, onde a(s) transformação(ões) aplicada(s) não afeta(m). No nosso caso, trata-se de um estado gráfico de nível superior.
Neste trecho de código, criamos o PsDocument a partir de um fluxo de saída e o PsSaveOptions, transladamos o estado gráfico de nível superior para os pontos 100 e 100 para deslocar o primeiro retângulo e, por fim, criamos o primeiro retângulo:
1//Create an output stream for PostScript document
2FileOutputStream outPsStream = new FileOutputStream(dataDir + "Tranformations_outPS.ps");
3//Create a save options with A4 size
4PsSaveOptions options = new PsSaveOptions();
5
6// Create new PS Document with the page opened
7PsDocument document = new PsDocument(outPsStream, options, false);
8
9document.translate(100, 100);
10
11//Create a rectangle
12Shape shape = new Rectangle2D.Float(0, 0, 150, 100);
Aqui, definimos a cor Laranja como a tinta atual para o estado gráfico de nível superior e preenchemos este retângulo.
O ficheiro PS resultante demonstrará a primeira forma localizada no estado gráfico de nível superior e que não sofreu qualquer transformação:
1////////////////////////////////////// No transformations ///////////////////////////////////////////////////////////////
2//Set paint in graphics state on upper level
3document.setPaint(Color.ORANGE);
4
5//Fill the first rectangle that is on on upper level graphics state and that is without any transformations.
6document.fill(shape);
7/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Agora, criamos um novo estado gráfico que será transladado em 250 pontos pelo eixo X em relação ao estado gráfico de nível superior e adicionamos a este novo estado gráfico o mesmo retângulo pintado com a cor Azul. No final, saímos do estado gráfico atual no estado gráfico de nível superior:
1////////////////////////////////////// Translation //////////////////////////////////////////////////////////////////////
2//Save graphics state in order to return back to this state after transformation
3document.writeGraphicsSave();
4
5//Displace current graphics state on 250 to the right. So we add translation component to the current transformation.
6document.translate(250, 0);
7
8//Set paint in the current graphics state
9document.setPaint(Color.BLUE);
10
11//Fill the second rectangle in the current graphics state (has translation transformation)
12document.fill(shape);
13
14//Restore graphics state to the previus (upper) level
15document.writeGraphicsRestore();
16/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Traduza o estado dos gráficos de nível superior para colocar os retângulos seguintes:
1//Displace on 200 to the bottom.
2document.translate(0, 200);
Aqui, criamos um estado gráfico que será dimensionado em 0,5 no eixo X e 0,75 no eixo Y e adicionamos a estes novos estados gráficos o mesmo retângulo pintado com a cor Vermelho. No final, saímos do estado gráfico atual para o estado gráfico de nível superior:
1////////////////////////////////////// Scaling //////////////////////////////////////////////////////////////////////////
2//Save the graphics state in order to return back to this state after transformation
3document.writeGraphicsSave();
4
5//Scale current graphics state on 0.5 in X axis and on 0.75f in Y axis. So we add scale component to the current transformation.
6document.scale(0.5f, 0.75f);
7
8//Set paint in the current graphics state
9document.setPaint(Color.RED);
10
11//Fill the third rectangle in the current graphics state (has scale transformation)
12document.fill(shape);
13
14//Restore graphics state to the previus (upper) level
15document.writeGraphicsRestore();
16//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Traduza o estado gráfico de nível superior para colocar os retângulos seguintes:
1//Displace upper level graphics state on 250 to the right.
2document.translate(250, 0);
De seguida, criamos um novo estado gráfico que será rodado 45 graus no sentido dos ponteiros do relógio em relação ao estado gráfico de nível superior e adicionamos a este novo estado gráfico o mesmo retângulo pintado com a cor Verde. No final, saímos do estado gráfico atual no estado gráfico de nível superior:
1////////////////////////////////////// Rotation //////////////////////////////////////////////////////////////////////
2//Save graphics state in order to return back to this state after transformation
3document.writeGraphicsSave();
4
5//Rotate current graphics state on 45 degrees around origin of current graphics state (350, 300). So we add rotation component to the current transformation.
6document.rotate(45);
7
8//Set paint in the current graphics state
9document.setPaint(Color.GREEN);
10
11//Fill the fourth rectangle in the current graphics state (has rotation transformation)
12document.fill(shape);
13
14//Restore graphics state to the previus (upper) level
15document.writeGraphicsRestore();
16//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Traduza o estado gráfico de nível superior para colocar os retângulos seguintes no espaço em branco da página.
1//Returns upper level graphics state back to the left and displace on 200 to the bottom.
2document.translate(-250, 200);
De seguida, criamos um novo estado gráfico que será distorcido e adicionamos a este novo estado gráfico o mesmo retângulo pintado com a cor Rosa. No final, saímos do estado gráfico atual no estado gráfico de nível superior:
1////////////////////////////////////// Shearing //////////////////////////////////////////////////////////////////////
2//Save graphics state in order to return back to this state after transformation
3document.writeGraphicsSave();
4
5//Shear current graphics state. So we add shear component to the current transformation.
6document.shear(0.1f, 0.2f);
7
8//Set paint in the current graphics state
9document.setPaint(new Color(255,192,203));
10
11//Fill the fifth rectangle in the current graphics state (has shear transformation)
12document.fill(shape);
13
14//Restore graphics state to the previous (upper) level
15document.writeGraphicsRestore();
16//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Traduza o estado gráfico de nível superior para colocar os retângulos seguintes no espaço em branco da página.
1//Displace upper level graphics state on 250 to the right.
2document.translate(250, 0);
Agora, criamos o último estado gráfico que irá sofrer uma transformação complexa, contendo componentes de translação, escala e rotação, e adicionamos a este novo estado gráfico o mesmo retângulo pintado com a cor Aquamarine. No final, saímos do estado gráfico atual para o estado gráfico de nível superior:
1////////////////////////////////////// Complex transformation ////////////////////////////////////////////////////////
2//Save graphics state in order to return back to this state after transformation
3document.writeGraphicsSave();
4
5//Transform current graphics state with complex transformation. So we add translation, scale and rotation components to the current transformation.
6document.transform(new AffineTransform(1.2f, -0.965925f, 0.258819f, 1.5f, 0f, 50));
7
8//Set paint in the current graphics state
9document.setPaint(new Color(127,255,212));
10
11//Fill the sixth rectangle in the current graphics state (has complex transformation)
12document.fill(shape);
13
14//Restore graphics state to the previus (upper) level
15document.writeGraphicsRestore();
16//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Traduza o estado gráfico de nível superior para colocar o último retângulo no espaço em branco da página:
1//Returns upper level graphics state back to the left and displace on 200 to the bottom.
2document.translate(-250, 200);
O último retângulo preenchido que colocámos novamente no estado gráfico de nível superior mostra que não sofreu transformações nos estados gráficos do nível inferior nem alterações de cor. A cor laranja é a tinta atual restante:
1////////////////////////////////////// Again no transformation ////////////////////////////////////////////////////////
2//Demonstrates that current graphics state's color is orange that was set up at the beginning of the code.
3//Fill the seventh rectangle in the current graphics state (has no transformation)
4document.fill(path);
5//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Por fim, fechamos a página atual e guardamos o documento:
1//Close current page
2document.closePage();
3
4//Save the document
5document.save();
6}
Veja como trabalhar com transformações no documento PS em .NET.
O resultado da execução deste código é o seguinte:
Pode descarregar exemplos e ficheiros de dados do GitHub.