Arbeiten mit Transformationen in PostScript | C++

Transformieren Sie einen Inhalt im PS-Dokument

In diesem Artikel betrachten wir, wie man verschiedene Transformationen durchführt: Verschiebung, Skalierung, Drehung und Scherung auf einem zu PsDocument hinzugefügten Rechteckpfad.

Wir teilen ein Code-Snippet in mehrere Codeteile auf: den Anfang, das Ende und jede Transformation separat. Eine Transformation in PostScript erfolgt immer in einem Grafikzustand, der durch die Operatoren “gsave” und “grestore” gebunden ist. Daher gibt es in unserem PsDocument die Methoden “WriteGraphicsSave()” und “WriteGraphicsRestore()”. Zwischen diesen Methoden können wir beliebige Inhalte hinzufügen, einschließlich des Zustands verschachtelter Grafiken, und beliebige Transformationen oder Beschneidungen vornehmen. Diese Transformationen wirken sich nicht auf äußere Grafikzustände aus, wohl aber auf verschachtelte.

Wenn wir eine Transformation ohne die Methoden “WriteGraphicsSave()” und “WriteGraphicsRestore()” durchführen, versetzen wir sie in den Grafikzustand der oberen Ebene und alle Inhalte, die sich in PsDocument befinden, werden dieser Transformation unterzogen .

Ein Algorithmus zum Festlegen einer Transformation für den Inhalt eines Dokuments von Grund auf umfasst die folgenden Schritte:

  1. Erstellen Sie einen Ausgabestream für die resultierende PS-Datei.
  2. Erstellen Sie PsSaveOptions.
  3. Erstellen Sie PsDocument mit dem bereits erstellten Ausgabestream und den Speicheroptionen.
  4. Speichern Sie einen Grafikstatus. Also haben wir einen neuen Grafikstatus erstellt, der vorherige Grafikstatus wurde in einen Grafikstatusstapel gelegt.
  5. Fügen Sie die erforderliche Transformation hinzu: Translation, Skalierung, Rotation, Scherung oder eine beliebige Kombination davon. In unserem Code zeigen wir den Einfluss jeder Transformationskomponente einzeln und am Ende jeweils drei.
  6. Fügen Sie den für die Transformation erforderlichen Inhalt hinzu. In unserem Fall haben wir aus dem Rechteck ein Rechteck GraphicsPath erstellt und es dann gefüllt. Wir haben vor allen Transformationen ein Rechteck erstellt und es nach jeder Transformation im aktuellen Grafikstatus einfach gefüllt.
  7. Stellen Sie den Grafikstatus wieder her, um zum vorherigen Zustand zurückzukehren, auf den sich die angewendeten Transformationen nicht auswirken. In unserem Fall handelt es sich um einen Grafikstatus der oberen Ebene.

In diesem Codeteil erstellen wir PsDocument aus einem Ausgabestream und PsSaveOptions, übersetzen den Grafikstatus der oberen Ebene in die Punkte 100,100, um das erste Rechteck zu versetzen, und erstellen schließlich das erste Rechteck GraphicsPath aus dem Rechteck.

 1    // The path to the documents directory.
 2    System::String dataDir = RunExamples::GetDataDir_WorkingWithCanvas();
 3    
 4    //Create output stream for PostScript document
 5    {
 6        System::SharedPtr<System::IO::Stream> outPsStream = System::MakeObject<System::IO::FileStream>(dataDir + u"Transformations_outPS.ps", System::IO::FileMode::Create);
 7        // Clearing resources under 'using' statement
 8        System::Details::DisposeGuard<1> __dispose_guard_0({ outPsStream});
 9        // ------------------------------------------
10        
11        try
12        {
13            //Create save options with default values
14            System::SharedPtr<PsSaveOptions> options = System::MakeObject<PsSaveOptions>();
15            
16            // Create new 1-paged PS Document
17            System::SharedPtr<PsDocument> document = System::MakeObject<PsDocument>(outPsStream, options, false);
18            
19            document->Translate(100.0f, 100.0f);
20            
21            //Create graphics path from the rectangle
22            System::SharedPtr<System::Drawing::Drawing2D::GraphicsPath> path = System::MakeObject<System::Drawing::Drawing2D::GraphicsPath>();
23            path->AddRectangle(System::Drawing::RectangleF(0.0f, 0.0f, 150.0f, 100.0f));

Hier legen wir die Farbe Orange als aktuelle Farbe für den Grafikstatus der oberen Ebene fest und füllen dieses Rechteck.

Die resultierende PS-Datei zeigt die erste Form, die sich im Grafikzustand der oberen Ebene befindet und keiner Transformation unterzogen wurde.

1            ////////////////////////////////////// No transformations ///////////////////////////////////////////////////////////////
2            //Set paint in graphics state on upper level
3            document->SetPaint(System::MakeObject<System::Drawing::SolidBrush>(System::Drawing::Color::get_Orange()));
4            
5            //Fill the first rectangle that is on on upper level graphics state and that is without any transformations.
6            document->Fill(path);
7            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Jetzt erstellen wir einen neuen Grafikzustand, der an 250 Punkten auf der X-Achse relativ zum Grafikzustand der oberen Ebene verschoben wird, und fügen diesem neuen Grafikzustand den gleichen rechteckigen Pfad hinzu, der mit der Farbe Blau bemalt ist. Am Ende verlassen wir den aktuellen Grafikstatus und wechseln zum Grafikstatus der oberen Ebene.

 1            ////////////////////////////////////// Translation //////////////////////////////////////////////////////////////////////
 2            
 3            //Save 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.0f, 0.0f);
 8            
 9            //Set paint in the current graphics state
10            document->SetPaint(System::MakeObject<System::Drawing::SolidBrush>(System::Drawing::Color::get_Blue()));
11            
12            //Fill the second rectangle in the current graphics state (has translation transformation)
13            document->Fill(path);
14            
15            //Restore graphics state to the previus (upper) level
16            document->WriteGraphicsRestore();
17            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Übersetzen Sie den Grafikstatus der oberen Ebene, um die nächsten Rechtecke zu platzieren.

1            //Displace on 200 to the bottom.
2            document->Translate(0.0f, 200.0f);

Hier erstellen wir einen Grafikzustand, der auf 0,5 auf der X-Achse und 0,75 auf der Y-Achse skaliert wird, und fügen zu diesem neuen Grafikzustand den gleichen rechteckigen Pfad hinzu, der mit der Farbe Rot bemalt ist. Am Ende verlassen wir den aktuellen Grafikstatus und wechseln zum Grafikstatus der oberen Ebene.

 1            ////////////////////////////////////// Scaling //////////////////////////////////////////////////////////////////////////
 2            //Save 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 paint in the current graphics state
 9            document->SetPaint(System::MakeObject<System::Drawing::SolidBrush>(System::Drawing::Color::get_Red()));
10            
11            //Fill the third rectangle in the current graphics state (has scale transformation)
12            document->Fill(path);
13            
14            //Restore graphics state to the previus (upper) level
15            document->WriteGraphicsRestore();
16            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Übersetzen Sie den Grafikstatus der oberen Ebene, um die nächsten Rechtecke zu platzieren.

1            //Displace upper level graphics state on 250 to the right.
2            document->Translate(250.0f, 0.0f);

Dann erstellen wir einen neuen Grafikstatus, der relativ zum Grafikstatus der oberen Ebene um 45 Grad im Uhrzeigersinn gedreht wird, und fügen diesem neuen Grafikstatus denselben rechteckigen Pfad hinzu, der mit der Farbe Grün bemalt ist. Am Ende verlassen wir den aktuellen Grafikstatus und wechseln zum Grafikstatus der oberen Ebene.

 1            ////////////////////////////////////// Rotation //////////////////////////////////////////////////////////////////////
 2            //Save 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 paint in the current graphics state
 9            document->SetPaint(System::MakeObject<System::Drawing::SolidBrush>(System::Drawing::Color::get_Green()));
10            
11            //Fill the fourth rectangle in the current graphics state (has rotation transformation)
12            document->Fill(path);
13            
14            //Restore graphics state to the previus (upper) level
15            document->WriteGraphicsRestore();
16            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Übersetzen Sie den Grafikstatus der oberen Ebene, um die nächsten Rechtecke in den leeren Bereich auf der Seite einzufügen.

1            //Returns upper level graphics state back to the left and displace on 200 to the bottom.
2            document->Translate(-250.0f, 200.0f);

Dann erstellen wir einen neuen Grafikzustand, der geschert wird, und fügen diesem neuen Grafikzustand den gleichen rechteckigen Pfad hinzu, der mit der Farbe Rosa bemalt ist. Am Ende verlassen wir den aktuellen Grafikstatus und wechseln zum Grafikstatus der oberen Ebene.

 1            ////////////////////////////////////// Shearing //////////////////////////////////////////////////////////////////////
 2            //Save 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 paint in the current graphics state
 9            document->SetPaint(System::MakeObject<System::Drawing::SolidBrush>(System::Drawing::Color::get_Pink()));
10            
11            //Fill the fifth rectangle in the current graphics state (has shear transformation)
12            document->Fill(path);
13            
14            //Restore graphics state to the previus (upper) level
15            document->WriteGraphicsRestore();
16            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Übersetzen Sie den Grafikstatus der oberen Ebene, um die nächsten Rechtecke in den leeren Bereich auf der Seite einzufügen.

1            //Displace upper level graphics state on 250 to the right.
2            document->Translate(250.0f, 0.0f);

Jetzt erstellen wir den letzten Grafikzustand, der einer komplexen Transformation mit Übersetzungs-, Skalierungs- und Rotationskomponenten unterzogen wird, und fügen diesem neuen Grafikzustand den gleichen rechteckigen Pfad hinzu, der mit der Farbe Aquamarin bemalt ist. Am Ende verlassen wir den aktuellen Grafikstatus und wechseln zum Grafikstatus der oberen Ebene.

 1            ////////////////////////////////////// Complex transformation ////////////////////////////////////////////////////////
 2            //Save 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(System::MakeObject<System::Drawing::Drawing2D::Matrix>(1.2f, -0.965925f, 0.258819f, 1.5f, 0.f, 50.0f));
 7            
 8            //Set paint in the current graphics state
 9            document->SetPaint(System::MakeObject<System::Drawing::SolidBrush>(System::Drawing::Color::get_Aquamarine()));
10            
11            //Fill the sixth rectangle in the current graphics state (has complex transformation)
12            document->Fill(path);
13            
14            //Restore graphics state to the previus (upper) level
15            document->WriteGraphicsRestore();
16            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Übersetzen Sie den Grafikstatus der oberen Ebene, um das letzte Rechteck in den leeren Bereich der Seite zu platzieren.

1            //Returns upper level graphics state back to the left and displace on 200 to the bottom.
2            document->Translate(-250.0f, 200.0f);

Das letzte gefüllte Rechteck, das wir wieder in den Grafikzustand der oberen Ebene eingefügt haben, zeigt, dass es keinen Transformationen der Grafikzustände der unteren Ebene und keinen Farbänderungen darin unterzogen wurde. Die orange Farbe ist die aktuelle Farbe.

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            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Abschließend schließen wir die aktuelle Seite und speichern das Dokument.

 1            //Close current page
 2            document->ClosePage();
 3            
 4            //Save the document
 5            document->Save();
 6        }
 7        catch(...)
 8        {
 9            __dispose_guard_0.SetCurrentException(std::current_exception());
10        }
11    }

Siehe Arbeiten mit Transformationen im PS-Dokument in .NET oder Java.


Das Ergebnis der Ausführung dieses Codes ist das nächste

Transformationen

Sie können Beispiele und Datendateien herunterladen von GitHub.

Have any questions about Aspose.Page?



Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.