天道酬勤

<<iText in Action 2nd>>5.3节(Overview of the page boundaries)读书笔记

前言

目前为止,我们通过Rectangle对象来定义页面的大小,而页面大小是PDF文档中5个不同页边界(page boundaries)的值。我们会在这一节中学习这些页边界,而且会通过一些列子来说明两个最重要页边界已经他们之间的区别。作者可以以自己的样子为模板画一个超人的图片,而且图片有1平方米,但为了避嫌,还是不画的好。但著名的商业画家Dick Kline曾经就为作者画过这样一幅画,并由长期使用iText的用户Bill Segraves送给了作者。

这幅画不是有原始的图片元素组成,是由一系列的贝加尔曲线构建而成,这些曲线存储在一个文本文件hero.txt中,以下为具体的代码:

listing 5.15 Hero1.cs

public PdfTemplate CreateTemplate(PdfContentByte content, Rectangle rect, int factor)
{
    PdfTemplate template = content.CreateTemplate(rect.Width, rect.Height);
    template.ConcatCTM(factor, 0, 0, factor, 0, 0);

    string filePath = ConfigurationManager.AppSettings["ResourceTxt"] + "hero.txt";
    FileStream fs = File.OpenRead(filePath);
    using (fs)
    {
        BinaryReader reader = new BinaryReader(fs);
        int c;
        while ((c = reader.Read()) > 1)
        {
            template.SetLiteral((char)c);
        }
    }

    return template;
}

在以上代码中我们创建PdfTemplate对象,然后通过SetLiteral方法直接写入PDF的语法,这个方法接受Char,float和String值。但大家在使用这个方法是要十分小心,因为使用不当则会对pdf文档造成损坏,在学习完14节之前大家还是不要用的好。原始的图本来是要添加到A4的纸张上,但作者希望将其添加到A0文档,因此将其缩放并设置了factor为4,创建A0大小的代码如下:

Document document = new Document(PageSize.A0);

以上代码定义的就是文档第一页的media box。

The media box

其实一直以来我们创建的文档只是用了一种类型的页边界:the media box。一下为media box的定义:

The media box defines the boundaries of the physical medium on which the page is to be printed. It may include any extended area surrounding the finished page for bleed, printing marks, or other such purposes. It may also include areas close to the edges of the medium that cannot be marked because of physical limitations of the output device. Content falling outside this boundary may safely be discarded without affecting the
meaning of the PDF file.

                                                                                                                                        —ISO-32000-1:2008, section 14.1.2

这里大概的意思就是media box是文档打印时对应设备的边界,其可以包括一些格外的信息而且内容超过边界对pdf文档没有什么影响。

在前面的代码中我们设置A0的纸张,在iText内部是以下代码实现的:

public static readonly Rectangle A0 = new RectangleReadOnly(2384,3370);

以上代码的意思是具体设备的度量为 2384 pt*3370pt(84.10cm*117.89cm or 33.11英寸*46.81英寸 )。在构造器中的2384和3370值配备页面的长和宽,但其实这是矩形的右上角坐标,因为左下角的坐标为0所以就忽视了。在第三节我们学习如何画线,画图以及对文本绝对定位的时候我们假设坐标系统的起点和页面的左下角一致。这个假设在media box将左下角定位(0,0)时是正确的,但这并不是强制这样规定。如果我们创建一个media box并使用不同的起点对一个应用程序而言是完全OK的,所以我们就有兴趣知道如果坐标系统的起点不在左下角那么会是神马情况,这也是作者创建超人图片的原因:

SuperMan

上图中的十字架就是坐标系统的起点(0,0)

listing 5.16 Hero1.cs (continued)

PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(fileName, FileMode.Create));
// step 3
document.Open();
// step 4
PdfContentByte content = writer.DirectContent;
PdfTemplate template = CreateTemplate(content, rect, 4);
content.AddTemplate(template, -1192, -1685);
content.MoveTo(-595, 0);
content.LineTo(595, 0);
content.MoveTo(0, -842);
content.LineTo(0, 842);
content.Stroke();

如果你有很多pdf文档,仔细观察的话你会发现绝大多数文档的坐标系统起点就是页面的左下角,但以上的这个列子告诉我们这并不一定是这样,理解这一点在后续我们学习操作已存在pdf文档时很有帮助。当坐标系起点不在左下角时我们对内容绝对定位就需要将坐标系统起点的值也计算进去,不然我们就有可能将内容天骄到不同的位置,甚至可能添加到页面可见区域的外部。但对于crop box类型的页边界来说我们要确认不要将添加的内容溢出。

The crop box

crop box是另一种页边界,其也可以通过Rectangle来定义但和以上提到的media box不同。crop box顾名思义就是裁剪的box,任何超过其边界的内容就会被裁剪掉,具体的说明大家可以看ISO的定义。在前面的列子中我们打印了一份A0的图片,但假设我们没有A0的打印机只有A4的打印机,那要如果打印出A0的效果图。根据标准A0的纸张对折四次就会变成A4的纸张,因此我们用A4的纸张打印16份不同的图片,然后在组装即可,具体的效果图如下:

SuperMan2

这里就牵扯到裁剪,我们的代码中就用到了SetCropBox方法来定义一个A4的crop box。

listing 5.17 Hero2.cs

float w = PageSize.A4.Width;
float h = PageSize.A4.Height;
Rectangle rect = new Rectangle(-2 * w, -2 * h, 2 * w, 2 * h);
Rectangle crop = new Rectangle(-2 * w, h, -w, 2 * h);
// step 2
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(fileName, FileMode.Create));
writer.CropBoxSize = crop;
// step 3
document.Open();
// step 4
PdfContentByte content = writer.DirectContent;
PdfTemplate template = CreateTemplate(content, rect, 4);
float adjust;
while (true)
{
    content.AddTemplate(template, -2 * w, -2 * h);
    adjust = crop.Right + w;
    if (adjust > 2 * w)
    {
        adjust = crop.Bottom - h;
        if (adjust < -2 * h)
        {
            break;
        }
        crop = new Rectangle(-2 * w, adjust, -w, crop.Bottom);
    }
    else
    {
        crop = new Rectangle(crop.Right, crop.Bottom, adjust, crop.Top);
    }

    writer.CropBoxSize = crop;
    document.NewPage();
}

在以上的代码中我们将内容添加到A0大小的文档中,但由于设置了SetCropBox方法,而且设置的crop box只有A4大小,这样添加的图片就会裁剪为crop box的大小,每次裁剪完之后就新开一页再次循环裁剪,最后将A0的图片成功裁剪为对应16份A4大小的文档。

这里如果我们并不立刻打印文档而是希望将此文档发送给设计师,并委托其给图片加上一些备注和其他的东西,但又不希望图片被修改或者被覆盖,因此我们需要为图片定义一个预保留区域。这里我们就可以使用art box来传递信息,art box也是剩下三个页边界其中之一。

other page boundaries

对于media box我们可以在Document的构造器中设置也可以通过PageSize属性设置,通过SetCropBox方法可以定义crop box,不过还有一个更加方便的方法SetBoxSize(string boxname,Rectangle size),这里容许传入的boxname为crop,bleed,trim和art。bleed box,trim box和art box对于具体的pdf阅览器来说比较重要,但对我们创建的文档则没有什么影响,如果大家对其感兴趣可以自行google看一些细节。这里我们要知道的是 对于crop,bleed,trim和art box来说其一般不应该超过media box的边界,如果超过边界则会影响其和media box的交互。以下为art box使用的代码:

listing 5.18 Hero3.cs

PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(fileName, FileMode.Create));
Rectangle art = new Rectangle(50, 0, 545, 792);
writer.SetBoxSize("art", art);
// step 3
document.Open();
// step 4
PdfContentByte content = writer.DirectContent;
PdfTemplate template = CreateTemplate(content, PageSize.A4, 1);
content.AddTemplate(template, 0, 0);

通过以上代码生成的pdf大家可以发现对图片和文档的编剧都没有什么影响,不过我们在下一节中使用art box来获取信息将其作为页眉和页脚。

总结

这一节主要是介绍一些页边界的类型,对于pdf文档来说media box和crop box是最重要的,而art box则一般被使用来写一些注释或者当作页眉页脚,在这一节中我们还知道坐标系统的起点并不一定和页面的左下角一致,最后就是代码下载了

同步

此文章已同步到目录索引:iText in Action 2nd 读书笔记。

同步

此文章已同步到目录索引:iText in Action 2nd 读书笔记。

posted @ 2012-07-19 19:23  JulyLuo  阅读(2117)  评论(0编辑  收藏  举报