Itextharp - 绘图形状和图形

以前的ITextSharp文章查看了将图像带入PDF文件并与它们一起工作。但是,有时,您可能希望在PDF中绘制形状和线路,而不依赖于图像。 ItextSharp包含大量功能,涵盖到相当复杂的形状。这篇文章让你开始了。以前的文章如下所示:

在ASP.NET中创建PDF - iTextSharp入门
iTextharp - 使用字体
iTextharp - 添加带有块,短语和段落的文本
列出ItextSharp.
iTextharp - 链接和书签
ITextSharp - 介绍表
iTextharp - 使用图像

到目前为止,以前文章中的PDF文档添加到PDF文档的所有内容都依赖于简单的借策文本,它负责在文档的流中定位内容。它还介绍创建新页面以接受溢出文本等。使用图形需要略有不同的方法,因为我们现在需要明确使用PDFContentByte()对象。这是从pdfwriter对象的directContent获得的。这也意味着我们实际上需要实例化PDFWriter对象的而不是刚刚调用PDFWriter的getInstance方法。

 

细绳 pdfpath = server.mappath(“pdfs”);

  文档 doc = 新的 文档();

  尝试

  {

    pdfwriter. 作家= pdfwriter..getInstance(Doc, 新的 filestream(pdfpath +. “/ groughics.pdf”, filemode.。创造));

    doc.Open();

    pdfcontentbyte. CB = Writer.DirectContent;
    ...

 

现在我们有一个工作的pdfcontentbyte对象,我们可以使用它来开始绘图:

 

cb.moveto(doc.pagesize.width / 2,doc.pagesize.height / 2);

cb.lineto(doc.pagesize.width / 2,doc.pageSize.height);

cb.stroke();

cb.moveto(0,doc.pagesize.height / 2);

cb.lineto(doc.pagesize.width,doc.pageSize.height / 2);

cb.stroke();

 

第一行移动到传入的参数中指定的x,y坐标,在这种情况下,该案例在文档中间,半向上(或中心点)。下一行从这一点绘制了一条线到Lineto()方法中指定的位置,这些位置仍然是文档的中途,但在其顶部。实际上,它没有"draw"它,但真的只描述了我们的意图。该行仅在调用STRAKE()时实际上致力于文档。第二行从左边缘绘制,在相同的高度的半个位置处的一个位置到右边 - 所以我们最终概述了文件的前两个季度。

使用相同的方法,我们可以将一个正方形添加到左上一季度:

 

cb.moveto(100f,700f);

cb.lineto(200f,700f);

CB.Lineto(200f,600f);

cb.lineto(100f,600f);

cb.closepath();

cb.stroke();

 

我们不需要明确地指定广场最终一侧的坐标。 ClosePath()自动提供我们在原始坐标的当前位置的一行。然而,使用ITextSharp提供的一种便利形状来提供方形(或矩形)的方式更快。下一个位显示为Action,将一个正方形放在文件的右上季度:

 

cb.rectangle(doc.pagesize.width-200f,600f,100f,100f);

cb.stroke();

 

页面中添加了四个更多的方块,每个方块都示出了scroke()以外的不同方法的结果,用于将它们托运到文档。但首先,设定行程颜色和填充颜色。如果您已使用Photoshop或Fireworks等任何图形软件包,您可能会知道笔划是对象的轮廓,并且填充表示由笔划界限的内部。我用CMYK作为颜色空间,将行程颜色设置为青色和填充颜色至黄色:

 

cb.setcolorstroke(新的 cmykcolor.(1f,0f,0f,0f));

CB.SetColorFill(新的 cmykcolor.(0f,0f,1f,0f));

 

CB.Moveto(70,200);

CB.Lineto(170,200);

CB.Lineto(170,300);

CB.Lineto(70,300);

//路径关闭并抚摸

cb.closepathstroke();

 

CB.Moveto(190,200);

CB.Lineto(290,200);

CB.Lineto(290,300);

CB.Lineto(190,300);

//填写,但未抚摸或关闭

cb.fill();

 

cb.moveto(310,200);

CB.Lineto(410,200);

CB.Lineto(410,300);

CB.Lineto(310,300);

//填写,抚摸,但路径未关闭

cb.fillstroke();

 

cb.moveto(430,200);

CB.Lineto(530,200);

CB.Lineto(530,300);

CB.Lineto(430,300);

//路径关闭,抚摸和填充

cb.closepathfilloke();

 

当使用矩形对象表示正方形或矩形而不是绘制它,前两个参数表示右下角的X和Y坐标。最终的两个参数是宽度和高度。其他预设形状包括圆圈,但是传递的x和y坐标表示形状的中心点,然后表示表示半径的值。在上面的4个方格中看第一,确定宽度和高度是100点相对容易,并且中心点为120 x,250 y。要将圆圈添加到广场,使其适合,以下代码将执行以下操作:

 

cb.setcmykcolortroke(255,255,0,0);

CB.SetCmykColorfill(0,255,255,0);
cb.SetLineWidth(2f);

cb.circle(120f,250f,50f);

cb.fill();

 

相当刺激性,我发现你必须猜测到了我到目前为止使用的三种方法的两种方法所需的实际值。鉴于通常,CMYK颜色也没有直观,表示为一系列百分比。例如,温度红色称为C:0%,M:100%,Y:100%,K:100%。 cmykcolor()的构造函数需要四个浮点数。提供表示百分比的值正常。但我提供了1F和0F的值。事实上,我可以提供我想要的任何价值,只要它是一个有效的浮点。该值被视为相对于彼此相对于彼此,因此对于100%蓝(青色),我可以有效地提供3000F,0f,0f,0f。奇怪,但如果您坚持通常的CMYK百分比,并且不要意外地键入额外的零点。

用于上面的setcmykcolorfill()方法接受INTS,而不是floats。我想也许这种方法正在研究我希望使用CMYK的百分比,所以我最初提供价值0,100,100,0表示温度红色。我所拥有的只是一个顽童的粉红色颜色。我想在那里有一个错误,而且有些东西受到填充颜色的前一个设置的影响,所以我部署了resetcmykcolorfill()方法,希望它做了一些东西。不。它所做的只是重置为黑色的默认颜色。最终,我发现CMYKColor是基于ExtendedColor类的,并且可以接受最多255的INT - 除非您知道,可以让人想起RGB颜色值,真正令人困惑。我申请了您在上面看到的值,并获得了所需的结果。要建立在这种方法的奇怪上,我还发现没有什么可以阻止你进入255以上的价值。如果你这样做,似乎ItextSharp从你提供的任何东西中减去255,所以256是相当于1,510是相当于255 - 或者至少,这是我尝试时得到的结果。

无论如何,足够的题外。这是我的红色圆圈,在第一架广场中的紫红色边框(宽度2点):

继续前进,这是使用另一种预设形状,椭圆的示例。首先,绘制矩形,然后添加椭圆形以简洁地适合它,以说明定位如何通过提供给构造函数的参数:

 

// x,左下角的y,宽度,高度

CB.Rectangle(100f,200f,300f,100f);

cb.stroke();

//左下角和右上坐标

cb.haripse(100f,200f,400f,300f);

cb.stroke();

 

如果第一和第三个参数之间的差异,并且第二和第四参数是相同的,则您最终将圆圈结束。

下一个示例显示了另一种预设形状,圆角矩形。当其中一个被绘制时,传入的值是左下角的x和y坐标,然后是宽度和高度,最后是圆角的半径。我还在角落里添加了一个圆圈,与角落本身相同的半径,以展示角落的半径如何工作。我在圈子的中心放了一条十字架:

 

//左下坐标,然后是宽度,高度和角落的半径

CB.Roundrectangle(100f,500f,200f,200f,20f);

cb.stroke();

 

cb.circle(120f,520f,20f);

cb.stroke();

 

cb.moveto(118f,520f);

CB.Lineto(122F,520F);

cb.stroke();

cb.moveto(120f,518f);

cb.lineto(120f,522f);

cb.stroke();

 

三角形是相对简单的,只是通过绘制他们所需的三条线。这是一个右角度三角形的示例,具有正确的角度:

 

cb.moveto(350f,450f);

cb.lineto(350f,600f);

cb.lineto(500f,450f);

cb.closepathstroke();

 

cb.moveto(350f,460f);

cb.lineto(360f,460f);

cb.lineto(360f,450f);

cb.stroke();

 

曲线和弧线

Bezier曲线在向量图形中很重要,在那里它们基于数学方程,而不是沿着曲线路径指定的每个单独的点。他们通过指定起点,终点和两个控制点来工作。参考起点指定第一控制点,第二个控制点与终点相关。曲线将在起始点开始,并且朝向第一控制点的方向朝向终点。它靠近控制点的距离将取决于起点和控制点之间的距离,以及端点及其控制点,以及开始和终点之间的距离。控制点用于定向目的,并且很少被路径击中。如果您曾使用过矢量图形包,则像Photoshop或Fireworks一样,您将看到这些控制点,通常很少"handles"在它们的末尾,您可以移动以弯曲曲线。

这是一个曲线的示例,它在(200,10)开始,并且在(350,150)结束。

 

//起点

cb.moveto(200f,10f);

//控制点1,控制点2,终点

CB.CurVeto(150F,30F,450F,70F,350F,150F);

cb.stroke();

 

在(150,30)朝向第一控制点朝向第一控制点朝向(450,70)弯曲,然后在到达终点之前朝向第二控制点弯曲。它看起来像这样:

我真的很确定会展示很多,所以我会添加一些"handles"显示控制点:

 

cb.moveto(200f,10f);

cb.lineto(150f,30f);

cb.stroke();

 

cb.moveto(450f,70f);

cb.lineto(350f,150f);

cb.stroke();

 

cb.circle(450f,70f,1f);

cb.stroke();

cb.circle(150f,30f,1f);

cb.stroke();

 

第一控制点具有相对短的手柄,因此曲线仅开始向其移动。第二个控制点具有更长的手柄,这开始在其旅程中的相对较早的点处与最终目的地一起发挥其影响,这在线的方式反映在线"pulled"朝着它。通过改变第二个控制点可能最好地说明这种效果,使其更远,并且该角度被改变:

 

cb.setcolorstroke(颜色。绿色);

//开始点(x,y)

cb.moveto(200f,10f);

//控制点1(x,y),控制点2(x,y),终点(x,y)

CB.curveto(150f,30f,550f,100f,350f,150f);

cb.stroke();

 

cb.moveto(550f,100f);

cb.lineto(350f,150f);

cb.stroke();

 

cb.circle(550f,100f,1f);

cb.stroke();

 

cb.setcolorstroke(颜色。浅灰);

 

//左下(x,y),右上右(x,y),开始角度,范围

CB.ARC(350F,70F,550F,130F,270F,90F);

cb.setlinedash(3f,3f);

cb.stroke();

 

cb.setlinedash(0f);

cb.moveto(550f,100f);

cb.lineto(535f,95f);

cb.stroke();

cb.moveto(550f,100f);

CB.Lineto(552F,88F);

cb.stroke();

 

原始曲线显示为黑色,而新的曲线显示为绿色。现在你可以看到第二个增加的长度"handle"从起点施加了它的影响力,因为绿线开始略微略微下方。由于新的第二控制点远离终点,并且处于稍微更钝的角度,因此在结束点之前,绿线在完成前进一步朝向第二控制点移动。

有几个其他要点有关第二曲线的代码有关。一个是在这种情况下使用的弧对象,以创建曲线箭头,示出了原始和新的第二控制点的移动。弧形是椭圆的一部分。在这种情况下,椭圆将适合于(350,70)的左下角的矩形和(550,130)。绘图绘制的默认方向是逆时针绘制的。弧启动的角度是270°, and only 90°它是绘制的。其次,在这一系列文章中首次示出了setLinedAsh()方法,允许我将箭头绘制为虚线。