Trabalhar com Transformações em PostScript | .NET
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á feita 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, criamos um retângulo GraphicsPath a partir do retângulo e preenchemo-lo. 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 GraphicsPath a partir do retângulo.
1//Create an output stream for PostScript document
2using (Stream outPsStream = new FileStream(dataDir + "Transformations_outPS.ps", FileMode.Create))
3{
4 //Create save options with default values
5 PsSaveOptions options = new PsSaveOptions();
6
7 // Create new 1-paged PS Document
8 PsDocument document = new PsDocument(outPsStream, options, false);
9
10 document.Translate(100, 100);
11
12 //Create graphics path from the rectangle
13 GraphicsPath path = new GraphicsPath();
14 path.AddRectangle(new RectangleF(0, 0, 150, 100));
Para Linux, MacOS e outros sistemas operativos não Windows, oferecemos a utilização do nosso pacote NuGet Aspose.Page.Drawing. Utiliza o backend Aspose.Drawing em vez da biblioteca de sistema System.Drawing.
Assim, importe o namespace Aspose.Page.Drawing em vez do System.Drawing. Nos excertos de código acima e seguintes, será utilizado Aspose.Page.Drawing.RectangleF em vez de System.Drawing.RectangleF, Aspose.Page.Drawing.Drawing2D.GraphicsPath em vez de System.Drawing.Drawing2D.GraphicsPath e assim por diante. Os nossos exemplos de código no GitHub contêm todas as substituições necessárias.
Aqui, definimos a cor Laranja como a pintura 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 a paint in graphics state on upper level
3 document.SetPaint(new SolidBrush(Color.Orange));
4
5 //Fill the first rectangle that is on on the upper-level graphics state and that is without any transformations.
6 document.Fill(path);
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 caminho retangular 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
3 //Save the graphics state in order to return back to this state after transformation
4 document.WriteGraphicsSave();
5
6 //Displace current graphics state on 250 to the right. So we add translation component to the current transformation.
7 document.Translate(250, 0);
8
9 //Set the paint in the current graphics state
10 document.SetPaint(new SolidBrush(Color.Blue));
11
12 //Fill the second rectangle in the current graphics state (has translation transformation)
13 document.Fill(path);
14
15 //Restore the graphics state to the previus (upper) level
16 document.WriteGraphicsRestore();
17/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Traduza o estado dos gráficos de nível superior para colocar os retângulos seguintes.
1 //Displace on 200 to the bottom.
2 document.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 percurso retangular 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
3 document.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.
6 document.Scale(0.5f, 0.75f);
7
8 //Set the paint in the current graphics state
9 document.SetPaint(new SolidBrush(Color.Red));
10
11 //Fill the third rectangle in the current graphics state (has scale transformation)
12 document.Fill(path);
13
14 //Restore the graphics state to the previus (upper) level
15 document.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.
2 document.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 caminho retangular 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 the graphics state in order to return back to this state after transformation
3 document.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.
6 document.Rotate(45));
7
8 //Set the paint in the current graphics state
9 document.SetPaint(new SolidBrush(Color.Green));
10
11 //Fill the fourth rectangle in the current graphics state (has rotation transformation)
12 document.Fill(path);
13
14 //Restore the graphics state to the previus (upper) level
15 document.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.
2 document.Translate(-250, 200);
De seguida, criamos um novo estado gráfico que será distorcido e adicionamos a este novo estado gráfico o mesmo caminho retangular 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 the graphics state in order to return back to this state after transformation
3 document.WriteGraphicsSave();
4
5 //Shear current graphics state. So we add shear component to the current transformation.
6 document.Shear(0.1f, 0.2f);
7
8 //Set the paint in the current graphics state
9 document.SetPaint(new SolidBrush(Color.Pink));
10
11 //Fill the fifth rectangle in the current graphics state (has shear transformation)
12 document.Fill(path);
13
14 //Restore the graphics state to the previus (upper) level
15 document.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.
2 document.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 caminho retangular 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 the graphics state in order to return back to this state after transformation
3 document.WriteGraphicsSave();
4
5 //Transform current graphics state with complex transformation. So we add translation, scale and rotation components to the current transformation.
6 document.Transform(new Matrix(1.2f, -0.965925f, 0.258819f, 1.5f, 0f, 50));
7
8 //Set the paint in the current graphics state
9 document.SetPaint(new SolidBrush(Color.Aquamarine));
10
11 //Fill the sixth rectangle in the current graphics state (has complex transformation)
12 document.Fill(path);
13
14 //Restore the graphics state to the previus (upper) level
15 document.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.
2 document.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)
4 document.Fill(path);
5//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Por fim, fechamos a página atual e guardamos o documento.
1 //Close current page
2 document.ClosePage();
3
4 //Save the document
5 document.Save();
6}
Veja como trabalhar com transformações no documento PS em Java.
O resultado da execução deste código é o seguinte:
Pode descarregar exemplos e ficheiros de dados do GitHub.