zoukankan      html  css  js  c++  java
  • iText7 For .Net 系列文章(二)文本布局、页眉、页脚、水印

      按照iText为.Net提供的入门教程 的安排,第二章应该是讲关于PDF的“低级内容”(原文中称为low-level content,可以理解为更底层内容)。教程中给出了画一个坐标轴、带网格线的坐标轴以及使用画布利用文本“拉扯”做出类似“星球大战”开场标题效果。参考教程个人写了一下,个人项目中实用性不大,这里就不出教程了。直接跳到第三章,第三章讲到利用基本构建块的高级方法与更底层的方法结合起来,做一个类似报纸排版效果的PDF文件、制作一个表格,重要列标注不同颜色、设置背景色、添加页眉、页脚、水印。

      实现报纸排版时遇到一个问题就是本人的文本内容是中文文本,直接使用教程中的代码发现仅文本内容中的英文内容显示在PDF中,调试发现内容从.txt文本文件中读取出来了,但是写入PDF文件就是没有显示,查阅资料发现是由于字体的原因,iText内置的字体都是英文字体,是不支持中文的。于是查阅资料实现注册中文字体功能,其中有个坑,需要注意,后续代码中会注明。

            private void newYorkTimesExampleToolStripMenuItem_Click(object sender, EventArgs e)
            {
                var fullFileName = GetSavingFileNameContainDirectory();
                if (string.IsNullOrWhiteSpace(fullFileName)) return;
                using (var fos = new FileStream(fullFileName, FileMode.Create))
                {
                    //Initialize PDF document
                    PdfDocument pdf = new PdfDocument(new PdfWriter(fos));
                    PageSize ps = PageSize.A5;
                    // Initialize document
                    Document document = new Document(pdf, ps);
                    //Set column parameters
                    float offSet = 36;
                    //这是官方实例三列的写法,此处实现为一列来展示
                    //float columnWidth = (ps.GetWidth() - offSet * 2 + 10) / 3;
                    //float columnHeight = ps.GetHeight() - offSet * 2;
                    ////Define column areas
                    //Rectangle[] columns = new Rectangle[] {
                    //    new Rectangle(offSet - 5, offSet, columnWidth, columnHeight),
                    //    new Rectangle(offSet + columnWidth, offSet, columnWidth, columnHeight),
                    //    new Rectangle(offSet + columnWidth * 2 + 5, offSet, columnWidth, columnHeight)
                    //    };
    
                    float columnWidth = ps.GetWidth() - offSet * 2 + 10;
                    float columnHeight = ps.GetHeight() - offSet * 2;
                    Rectangle[] columns = new Rectangle[] { new Rectangle(offSet - 5, offSet, columnWidth, columnHeight) };
                    document.SetRenderer(new ColumnDocumentRenderer(document, columns));
                    // adding content
                    string INST_IMG = @"此处添加图片完整路径,也可修改为选择图片";
                    Image inst = new Image(ImageDataFactory.Create(INST_IMG)).SetWidth(columnWidth);
                    string INST_TXT = @"此处添加文本内容.txt文件完整路径,其他格式也是允许的";
                    String articleInstagram = File.ReadAllText(System.IO.Path.Combine(INST_TXT), Encoding.UTF8);
                    NewYorkTimes.AddArticle(document, "Instagram May Change Your Feed, Personalizing It With an Algorithm"
                                    , "By MIKE ISAAC MARCH 15, 2016", inst, articleInstagram);
                    document.Close();
                }
            }
    
        public class NewYorkTimes
        {
            public static void AddArticle(Document doc, String title, String author, iText.Layout.Element.Image img, String text)
            {
                var timesNewRomanBold = PdfFontFactory.CreateFont(StandardFonts.TIMES_BOLD);
                var timesNewRoman = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN);
                //PdfFontFactory.RegisterSystemDirectories();
                //获取已注册的字体名称
                //List<string> registeredFonts = PdfFontFactory.GetRegisteredFonts().ToList();
    
                //词汇必须在路径后面加上,0 不然PdfFontFactory.CreateRegisteredFont会返回null
                //此路径为windows操作系统自带的微软雅黑-标准字体
                FontProgramFactory.RegisterFont(@"C:\Windows\Fonts\msyh.ttc,0", "yaHei_font");
                PdfFont myBoldFont = PdfFontFactory.CreateRegisteredFont("yaHei_font", PdfEncodings.IDENTITY_H, EmbeddingStrategy.FORCE_EMBEDDED);
                var grayColor = new DeviceCmyk(0, 0, 0, 0.875f);
                Paragraph p1 = new Paragraph(title).SetFont(timesNewRomanBold).SetFontSize(14);
                doc.Add(p1);
                doc.Add(img);
                Paragraph p2 = new Paragraph().SetFont(timesNewRoman).SetFontSize(7).SetFontColor(grayColor).Add(author);
                doc.Add(p2);
                Paragraph p3 = new Paragraph().SetFont(myBoldFont).SetFontSize(10).Add(text);
                doc.Add(p3);
            }
        }     

    大致效果如下图:

     添加页眉、页脚、背景色、水印,参考教程大部分内容都没问题,就是教程中添加水印功能块存在较大问题,程序会转换异常错误。又是一顿查阅资料,发现使用Canvas.SetProperty(int ,object)方法设置画笔属性时必须根据不同属性传对应的对象类型,不能像教程一样,字体大小直接传一个60的数值。自己添加了一种写起来更加简单的方式,供选择。

            private void waterMarkExampleToolStripMenuItem_Click(object sender, EventArgs e)
            {
                var fullFileName = GetSavingFileNameContainDirectory();
                if (string.IsNullOrWhiteSpace(fullFileName)) return;
                using (var fos = new FileStream(fullFileName, FileMode.Create))
                {
                    //Initialize PDF document
    
                    PdfDocument pdf = new PdfDocument(new PdfWriter(fos));
    
                    pdf.AddEventHandler(PdfDocumentEvent.END_PAGE, new MyEventHandler(this));
    
                    // Initialize document
    
                    Document document = new Document(pdf);
    
                    Paragraph p = new Paragraph("List of reported UFO sightings in 20th century")
                        .SetTextAlignment(TextAlignment.CENTER)
                        .SetFont(iText.Kernel.Font.PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD))
                        .SetFontSize(14);
    
                    document.Add(p);
    
                    Table table = new Table(new float[] { 3, 5, 7, 4 });
    
                    table.SetWidth(UnitValue.CreatePercentValue(100));
    
                    StreamReader sr = File.OpenText(GetOpeningFileNameContainDirectory());
    
                    String line = sr.ReadLine();
    
                    Process(table, line, iText.Kernel.Font.PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD), true);
    
                    while ((line = sr.ReadLine()) != null)
                    {
                        Process(table, line, iText.Kernel.Font.PdfFontFactory.CreateFont(StandardFonts.HELVETICA), false);
                    }
    
                    sr.Close();
    
                    document.Add(table);
    
                    document.Close();
                }
            }
    
    public void Process(Table table, String line, PdfFont font, bool isHeader)
            {
                StringTokenizer tokenizer = new StringTokenizer(line, ";");
                int columnNumber = 0;
                var greenColor = new DeviceCmyk(1, 0, 1, 0.176f);
                var blueColor = new DeviceCmyk(1, 0.156f, 0, 0.118f);
                var yellowColor = new DeviceRgb(System.Drawing.Color.Yellow.R, System.Drawing.Color.Yellow.G, System.Drawing.Color.Yellow.B);
                var redColor = new DeviceRgb(System.Drawing.Color.Red.R, System.Drawing.Color.Red.G, System.Drawing.Color.Red.B);
    
                while (tokenizer.HasMoreTokens())
                {
                    if (isHeader)
                    {
                        Cell cell = new Cell().Add(new Paragraph(tokenizer.NextToken()));
                        cell.SetNextRenderer(new RoundedCornersCellRenderer(cell));
                        cell.SetPadding(5).SetBorder(null);
                        table.AddHeaderCell(cell);
                    }
                    else
                    {
                        columnNumber++;
                        Cell cell = new Cell().Add(new Paragraph(tokenizer.NextToken()));
                        cell.SetFont(font).SetBorder(new iText.Layout.Borders.SolidBorder(new DeviceRgb(System.Drawing.Color.Black.R, System.Drawing.Color.Black.G, System.Drawing.Color.Black.B), 0.5f));
                        switch (columnNumber)
                        {
                            case 4:
                                {
                                    cell.SetBackgroundColor(greenColor);
                                    break;
                                }
                            case 5:
                                {
                                    cell.SetBackgroundColor(yellowColor);
                                    break;
                                }
                            case 6:
                                {
                                    cell.SetBackgroundColor(redColor);
                                    break;
                                }
                            default:
                                {
                                    cell.SetBackgroundColor(blueColor);
                                    break;
                                }
                        }
                        table.AddCell(cell);
                    }
                }
            }
    
        public class RoundedCornersCellRenderer : CellRenderer
        {
            public RoundedCornersCellRenderer(Cell modelElement)
                : base(modelElement)
            {
    
            }
    
            public override void DrawBorder(DrawContext drawContext)
            {
                Rectangle rectangle = this.GetOccupiedAreaBBox();
                float llx = rectangle.GetX() + 1;
                float lly = rectangle.GetY() + 1;
                float urx = rectangle.GetX() + this.GetOccupiedAreaBBox().GetWidth() - 1;
                float ury = rectangle.GetY() + this.GetOccupiedAreaBBox().GetHeight() - 1;
                PdfCanvas canvas = drawContext.GetCanvas();
                float r = 4;
                float b = 0.4477f;
                canvas.MoveTo(llx, lly).LineTo(urx, lly).LineTo(urx, ury - r).CurveTo(urx, ury - r * b, urx - r * b, ury,
                    urx - r, ury).LineTo(llx + r, ury).CurveTo(llx + r * b, ury, llx, ury - r * b, llx, ury - r).LineTo(llx
                    , lly).Stroke();
                base.DrawBorder(drawContext);
            }
        }
    
        public class MyEventHandler : IEventHandler
        {
            public MyEventHandler(Form enclosing)
            {
                _enclosing = enclosing;
            }
            public virtual void HandleEvent(Event @event)
            {
                PdfDocumentEvent docEvent = (PdfDocumentEvent)@event;
                PdfDocument pdfDoc = docEvent.GetDocument();
                PdfPage page = docEvent.GetPage();
                int pageNumber = pdfDoc.GetPageNumber(page);
                Rectangle pageSize = page.GetPageSize();
                PdfCanvas pdfCanvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), pdfDoc);//此方式,水印在内容下层,会被文本内容遮挡
                //Set background
                Color limeColor = new DeviceCmyk(0.208f, 0, 0.584f, 0);
                Color blueColor = new DeviceCmyk(0.445f, 0.0546f, 0, 0.0667f);
                var helveticaFont = iText.Kernel.Font.PdfFontFactory.CreateFont(StandardFonts.HELVETICA);
                var helveticaBoldFont = iText.Kernel.Font.PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD);
    
                pdfCanvas.SaveState()
                            .SetFillColor(pageNumber % 2 == 1 ? limeColor : blueColor)
                            .Rectangle(pageSize.GetLeft(), pageSize.GetBottom(), pageSize.GetWidth(), pageSize.GetHeight())
                            .Fill()
                            .RestoreState();
    
                //Add header and footer
                pdfCanvas.BeginText()
                            .SetFontAndSize(helveticaFont, 9)
                            .MoveText(pageSize.GetWidth() / 2 - 60, pageSize.GetTop() - 20)
                            .ShowText("THE TRUTH IS OUT THERE")
                            .MoveText(60, -pageSize.GetTop() + 30)
                            .ShowText(pageNumber.ToString())
                            .EndText();
    
                PdfCanvas overCanvas = new PdfCanvas(page);//水印在内容上面,不会被遮挡
                //Add watermark
                Color whiteColor = new DeviceRgb(System.Drawing.Color.White.R, System.Drawing.Color.White.G, System.Drawing.Color.White.B);
                Color blackColor = new DeviceRgb(System.Drawing.Color.Black.R, System.Drawing.Color.Black.G, System.Drawing.Color.Black.B);
    
                //方式1
                //iText.Layout.Canvas canvas = new iText.Layout.Canvas(overCanvas, page.GetPageSize());
                //UnitValue fontSize = new UnitValue(UnitValue.POINT, 60);
                //TransparentColor fontColor = new TransparentColor(whiteColor, 0.8f);
                ////不能使用注释掉的方式(注释内容是入门教程中的写法)去设置文本的样式,不然在ShowTextAligned中会报转换异常
                //canvas.SetProperty(Property.FONT_COLOR, fontColor);//canvas.SetProperty(Property.FONT_COLOR, whiteColor);
                //canvas.SetProperty(Property.FONT_SIZE, fontSize);//canvas.SetProperty(Property.FONT_SIZE, 60);
                //canvas.SetProperty(Property.FONT, helveticaBoldFont);
                //canvas.ShowTextAligned(new Paragraph("CONFIDENTIAL"), 298, 421, pdfDoc.GetPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
                //canvas.Close();
    
                //方式2 推荐方式2,书写更简单
                //overCanvas.SaveState();
                //Paragraph paragraph = new Paragraph("CONFIDENTIAL")
                //        .SetFont(helveticaBoldFont)
                //        .SetFontSize(60)
                //        .SetFontColor(whiteColor)
                //        .SetOpacity(0.8f);
                ////直接给Paragraph设置透明度比下面这种方式更简单
    
                ////PdfExtGState gs1 = new PdfExtGState();
                ////gs1.SetFillOpacity(0.5f);//设置透明度
                ////overCanvas.SetExtGState(gs1);
                //Canvas canvasWatermark1 = new Canvas(overCanvas, pdfDoc.GetDefaultPageSize())
                //        .ShowTextAligned(paragraph, 298, 421, pdfDoc.GetPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
                //canvasWatermark1.Close();
                //overCanvas.RestoreState();
    
                pdfCanvas.Release();
            }
    
            private readonly Form _enclosing;
        }

    里面添加了单元格样式、PDF处理事件两个类,用于实现自定义的单元格样式和页眉、页脚、背景色、水印自定义事件(每次发生 PdfDocumentEvent.END_PAGE 类型的事件时都会触发此方法。即:每次 iText 完成向页面添加内容时,要么是因为创建了新页面,要么是因为已到达并完成最后一页。查看了一下END_PAGE的解释就是 在页面刷新到文档之前调度的事件类型)。效果如下图,背景色按照奇数柠檬黄、偶数绿色设置,但是其中有一个问题,除了第一页第一行有圆角设置外后面页的第一行标题没有格式,这个问题抽时间解决后再来更新一下文章,如果知道的小伙伴在评论里留言指出我会非常感谢。

     如果该文章对你有所帮助,还望推荐一下。如果慷慨的你愿意打赏,那就再好不过了。

    本文来自博客园,作者:业荒于嬉,转载请注明原文链接:https://www.cnblogs.com/FreeLoopPowter/p/15687440.html

    如内容对您有所帮助,还请不吝推荐一下!

  • 相关阅读:
    在 Cocos2d-x 中添加自己的微博链接
    关于屏幕适配
    [抽象工厂模式]在游戏开发中的应用
    字符串排列组合
    子矩阵最大和
    网易游戏编程题第二题
    动态规划,最大子段和
    C++的四种显示类型转换
    多线程编程
    预处理等等
  • 原文地址:https://www.cnblogs.com/FreeLoopPowter/p/15687440.html
Copyright © 2011-2022 走看看