iTextSharp CreateInk方法:曲线和角点 [英] iTextSharp CreateInk method: curves and corners

查看:143
本文介绍了iTextSharp CreateInk方法:曲线和角点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用iTextSharp在PDF文档中使用PdfAnnotation.CreateInk绘制标记图形。我正在尝试绘制矩形,传递五个坐标的数组。我知道iTextSharp有一个绘制矩形的专用函数,但我只想用一种方法来绘制我需要的各种标记行,而CeateInk似乎应该能够做到这一点。



问题是CreateInk是用曲线而不是角来绘制矩形。我一直无法弄清楚如何改变这一点。



支持注释,包括根据规范生成外观。



有自己的外表



 使用(PdfReader pdfReader = new PdfReader(inputPath))
using(PdfStamper pdfStamper = new PdfStamper(pdfReader,outputStream))
{
Rectangle pageSize = pdfReader.GetPageSize(1);
PdfArray vertices = new PdfArray(new int [] {100,100,300,300,100,300,300,100});
PdfAnnotation polyLine = PdfAnnotation.CreatePolygonPolyline(pdfStamper.Writer,pageSize,
,false,vertices);
polyLine.Color = BaseColor.GREEN;

PdfAppearance appearance = PdfAppearance.CreateAppearance(pdfStamper.Writer,pageSize.Width,pageSize.Height);
appearance.SetColorStroke(BaseColor.RED);
appearance.MoveTo(100,100);
appearance.LineTo(300,300);
appearance.LineTo(100,300);
appearance.LineTo(300,100);
appearance.Stroke();

polyLine.SetAppearance(PdfName.N,appearance);
pdfStamper.AddAnnotation(polyLine,1);
}

添加此





支持注释的PDF查看器,根据规范提供注释。



(我在外观上明确使用了不同的颜色,以确保PDF查看器显示我的外观,而不是自己创建一个。)


I'm using iTextSharp to draw markup graphics in PDF documents, using PdfAnnotation.CreateInk. I'm trying to draw rectangles, passing in an array of five co-ordinates. I know iTextSharp has a dedicated function for drawing rectangles, but I'm trying to use just one method to draw the various kinds of markup lines I need, and it seems that CeateInk should be able to do that.

The problem is that CreateInk is drawing the rectangle with curves rather than corners. I haven't been able to figure out how to change this. This answer suggests that the solution might be to create a PdfAppearance; I haven't yet figured out whether that will work. Here's my code (the first bit converts a list of list of points to an array of arrays, which InkList requires):

    public void MarkupInk(List<List<float>> InkList){   
    float[][] Coords = new float[InkList.Count][];                      
    for (int i = 0; i < InkList.Count; i++) {                   
        float[] thisarr = InkList [i].ToArray ();
        Coords[i] = new float[InkList[i].Count];
        System.Array.Copy (thisarr, Coords [i], InkList [i].Count);  
    }
    using(MemoryStream ms = new MemoryStream ()){   
        PdfReader reader = new PdfReader (textmaster.pdfDocArr);
        PdfStamper stamper = new PdfStamper (reader, ms);
        pagerect = reader.GetPageSize (textmaster.currentfirstpage + 1);
        PdfAnnotation an2 = PdfAnnotation.CreateInk (stamper.Writer, pagerect, "", Coords);
        an2.Color = strokeColor;
        an2.BorderStyle = new PdfBorderDictionary (strokeWeight, PdfBorderDictionary.STYLE_SOLID);
        stamper.AddAnnotation (an2, textmaster.currentfirstpage+1);
        stamper.Close ();
        textmaster.pdfDocArr = ms.ToArray ();
        reader.Close ();
    }
}

Any suggestions are much appreciated. Thanks!

EDIT: following @mkl's code I now have code that creates PDFAnnotations with appearances. And most of those annotations show up correctly in the viewing applications I use. But there is one odd behavior that I have not been able to fix.

What's happening is that the most recently created annotation does not appear in the viewing applications until I've created another annotation. So if I create annotation A, it's invisible until I create annotation B, at which point annotation A appears and B does not. Creating annotation C causes annotation B to appear, and so on.

This behavior persists even if I close the pdf file and the viewing application and re-load from disk. So the data describing the last-created annotation exists as part of the pdf file, but it doesn't render until I've created a new annotation.

I suspect there's something I'm still missing in the code I'm using to create the annotations and pdfAppearances. Here's code that creates a single line annotation:

public void WriteLineAnnotation(List<float> polyCoords){    

    using (MemoryStream ms = new MemoryStream ()) {
        PdfReader reader = new PdfReader (textmaster.pdfDocArr);
        PdfStamper stamper = new PdfStamper (reader, ms) { AnnotationFlattening = true };
        pagerect = reader.GetPageSize (textmaster.currentfirstpage + 1);

        //Create the pdfAnnotation polyline
        PdfAnnotation polyann = PdfAnnotation.CreatePolygonPolyline (stamper.Writer, pagerect, "", false, new PdfArray (polyCoords.ToArray ()));
        polyann.Color = strokeColor;
        polyann.BorderStyle = new PdfBorderDictionary (strokeWeight, PdfBorderDictionary.STYLE_SOLID);
        polyann.Flags = iTextSharp.text.pdf.PdfAnnotation.FLAGS_PRINT;

        //create the PdfAppearance and set attributes
        PdfAppearance app = PdfAppearance.CreateAppearance (stamper.Writer, pagerect.Width, pagerect.Height);
        app.SetColorStroke (strokeColor);
        app.MoveTo (polyCoords [0], polyCoords [1]);
        app.LineTo (polyCoords [2], polyCoords [3]);
        app.Stroke ();

        //set the annotation's appearance, add annotation, clean up
        polyann.SetAppearance (PdfName.N, app);
        stamper.AddAnnotation (polyann, textmaster.currentfirstpage + 1);
        stamper.Close ();
        reader.Close ();

        //create bytearray from memorystream and send to pdf renderer
        textmaster.pdfDocArr = ms.ToArray ();
    }
}

[/code]

Is there something obvious that I'm missing? Thanks in advance for any help.

解决方案

Which annotation type to use

I know iTextSharp has a dedicated function for drawing rectangles, but I'm trying to use just one method to draw the various kinds of markup lines I need, and it seems that CeateInk should be able to do that.

Please be aware that iText not merely has separate functions for those different forms, these different functions also create different types of PDF annotations.

In particular the Ink annotation -- which you would like to use for all forms -- is specified as

An ink annotation (PDF 1.3) represents a freehand "scribble" composed of one or more disjoint paths.

(Section 12.5.6.13 - Ink Annotations - ISO 32000-1)

As a freehand "scribble" commonly is not considered to be a sequence of straight lines and sharp corners but instead more soft and rounded; thus, it is only natural that PDF viewers will display an ink annotation given by coordinates of the corners of a rectangle with curves rather than corners.

Of course you can use an appearance stream to provide a visualization of the appearance but that would be a small misuse of this PDF feature.

Instead I would propose you use a different kind of annotation to draw the various kinds of markup lines you need: Polyline annotations. They are specified as:

Polygon annotations (PDF 1.5) display closed polygons on the page. Such polygons may have any number of vertices connected by straight lines. Polyline annotations (PDF 1.5) are similar to polygons, except that the first and last vertex are not implicitly connected.

(Section 12.5.6.9 - Polygon and Polyline Annotations - ISO 32000-1)

iText(Sharp) provides a method for this kind of annotations, too:

/**
 * Creates a polygon or -line annotation
 * @param writer the PdfWriter
 * @param rect the annotation position
 * @param contents the textual content of the annotation
 * @param polygon if true, the we're creating a polygon annotation, if false, a polyline
 * @param vertices an array with the vertices of the polygon or -line
 * @since 5.0.2
 */
public static PdfAnnotation CreatePolygonPolyline(
    PdfWriter writer, Rectangle rect, String contents, bool polygon, PdfArray vertices)

You might eventually still have to create annotations as not all PDF viewers, in particular so called "pre-viewers", generate appearances but instead count on appearances being provided in PDFs they pre-display...

Examples

Without own appearance

using (PdfReader pdfReader = new PdfReader(inputPath))
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream))
{
    PdfArray vertices = new PdfArray(new int[]{ 100, 100, 300, 300, 100, 300, 300, 100 });
    PdfAnnotation polyLine = PdfAnnotation.CreatePolygonPolyline(pdfStamper.Writer, pdfReader.GetPageSize(1),
        "", false, vertices);
    polyLine.Color = BaseColor.GREEN;
    pdfStamper.AddAnnotation(polyLine, 1);
}

adds this:

in PDF viewers supporting annotations including appearance generation according to the specification.

With own appearance

using (PdfReader pdfReader = new PdfReader(inputPath))
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream))
{
    Rectangle pageSize = pdfReader.GetPageSize(1);
    PdfArray vertices = new PdfArray(new int[] { 100, 100, 300, 300, 100, 300, 300, 100 });
    PdfAnnotation polyLine = PdfAnnotation.CreatePolygonPolyline(pdfStamper.Writer, pageSize,
        "", false, vertices);
    polyLine.Color = BaseColor.GREEN;

    PdfAppearance appearance = PdfAppearance.CreateAppearance(pdfStamper.Writer, pageSize.Width, pageSize.Height);
    appearance.SetColorStroke(BaseColor.RED);
    appearance.MoveTo(100, 100);
    appearance.LineTo(300, 300);
    appearance.LineTo(100, 300);
    appearance.LineTo(300, 100);
    appearance.Stroke();

    polyLine.SetAppearance(PdfName.N, appearance);
    pdfStamper.AddAnnotation(polyLine, 1);
}

adds this

in PDF viewers supporting annotations which bring along their annotation according to the specification.

(I explicitly used a different color in my appearance to make sure the PDF viewer shows my appearance and does not create one itself.)

这篇关于iTextSharp CreateInk方法:曲线和角点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆