在 PostScript 中使用转换 | C++
在 PS 文档中转换内容
本文将探讨如何在添加到 PsDocument 的矩形路径上进行不同的转换:平移、缩放、旋转和剪切。
我们将一个代码片段拆分成几段代码:开头、结尾和每个转换部分。PostScript 中的转换始终在受 “gsave” 和 “grestore” 运算符绑定的图形状态下进行。因此,在我们的 PsDocument 中,有 “WriteGraphicsSave()” 和 “WriteGraphicsRestore()” 方法。在这些方法之间,我们可以添加任何内容,包括嵌套的图形状态,并进行任何转换或剪切。这些转换不会影响外部图形状态,但会影响嵌套的图形状态。
如果我们不使用**“WriteGraphicsSave()”和“WriteGraphicsRestore()”**方法进行转换,则会在上层的图形状态下进行转换,并且 PsDocument 中的所有内容都将进行此转换。
从头开始对文档内容设置任何转换的算法包括以下步骤:
- 为生成的 PS 文件创建输出流。
- 创建 PsSaveOptions。
- 使用已创建的输出流和保存选项创建 PsDocument。
- 保存图形状态。我们创建了一个新的图形状态,之前的图形状态被放入图形状态堆栈中。
- 添加必要的变换:平移、缩放、旋转、剪切或其任意组合。在我们的代码中,我们分别显示每个变换组件的影响,最后一次显示三个变换组件的影响。
- 添加变换所需的必要内容。在我们的例子中,我们从该矩形创建了一个矩形 GraphicsPath,然后填充它。我们在进行任何变换之前创建一个矩形,并在当前图形状态下每次变换后填充它。
- 恢复图形状态,使其返回到之前应用的变换不受影响的状态。在本例中,它是一个上层图形状态。
在这段代码中,我们从输出流和 PsSaveOptions 创建 PsDocument,将上层图形状态平移到点 100,100 以偏移第一个矩形,最后从该矩形创建第一个矩形 GraphicsPath。
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));
这里我们将橙色设置为上层图形状态的当前绘制颜色,并填充此矩形。
生成的 PS 文件将显示位于上层图形状态且未经过任何变换的第一个形状。
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 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
现在,我们创建一个新的图形状态,该状态将相对于上一级图形状态沿 X 轴平移 250 个点,并向该新图形状态添加相同的矩形路径,该矩形路径以蓝色绘制。最后,我们从当前图形状态退出到上一级图形状态。
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 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
转换上层图形状态以便放置下一个矩形。
1 //Displace on 200 to the bottom.
2 document->Translate(0.0f, 200.0f);
这里我们创建一个图形状态,其 X 轴缩放 0.5,Y 轴缩放 0.75,并将相同的矩形路径添加到这些新的图形状态中,该矩形路径以红色绘制。 最后,我们从当前图形状态退出,并跳转到上一级图形状态。
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 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
转换上层图形状态以便放置下一个矩形。
1 //Displace upper level graphics state on 250 to the right.
2 document->Translate(250.0f, 0.0f);
然后,我们创建一个新的图形状态,该状态将相对于上一级图形状态顺时针旋转 45 度,并向该新图形状态添加相同的矩形路径,该矩形路径以绿色绘制。最后,我们从当前图形状态退出到上一级图形状态。
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 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
翻译上层图形状态以便将下一个矩形放置在页面的空白处。
1 //Returns upper level graphics state back to the left and displace on 200 to the bottom.
2 document->Translate(-250.0f, 200.0f);
然后,我们创建一个将被剪切的新图形状态,并将相同的矩形路径(用粉色绘制)添加到这个新的图形状态中。 最后,我们从当前图形状态退出到上一级图形状态
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 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
翻译上层图形状态以便将下一个矩形放置在页面的空白处。
1 //Displace upper level graphics state on 250 to the right.
2 document->Translate(250.0f, 0.0f);
现在,我们创建最后一个图形状态,该状态将经历包含平移、缩放和旋转等复杂变换,并将相同的矩形路径(使用海蓝宝石颜色绘制)添加到此新的图形状态。 最后,我们从当前图形状态退出,并跳转到上一级图形状态。
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 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
翻译上层图形状态,以便将最后一个矩形放置在页面的空白处。
1 //Returns upper level graphics state back to the left and displace on 200 to the bottom.
2 document->Translate(-250.0f, 200.0f);
我们再次将最后一个填充的矩形放入上层图形状态,这表明它没有经历下层图形状态的变换,也没有发生颜色变化。 橙色代表当前绘制的颜色。
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 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
最后我们关闭当前页面并保存文档。
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 }
运行此代码的结果是下一个
您可以从 GitHub下载示例和数据文件。