Click here to Skip to main content
12,448,709 members (55,130 online)
Click here to Skip to main content
Add your own
alternative version

Stats

84.5K views
805 downloads
54 bookmarked
Posted

Another PDFLib - Part1: Show text and draw graphs

, 4 Jan 2006
Rate this:
Please Sign up or sign in to vote.
A .NET library to create PDF files manually.

Introduction

PDF files are becoming more and more popular; we may need a library to manipulate these PDF files in our application without using Acrobat SDK. Although, there are such libraries available I thought of creating my own. The library supports Unicode inside PDF objects and selection of encoding, so that I can use Chinese characters freely in a PDF document.

The library is written in C# and requires .NET 2.0.

This project is intended to achieve all the capabilities specified in PDF 1.6 Reference, and provides tools to create, read, and manipulate PDF files. This library is only a startup.

The current capabilities:

  • Basic data types (Number, String, DateTime, Array, Dictionary, Stream...)
  • File structure and document structure
  • Path construction and painting
  • Graphics state
  • Transformation matrices
  • Form XObjects
  • Text state
  • Text objects
  • Type 1 fonts
  • Composite font from type 0 CIDFont
  • Document outline and PageLables
  • ViewerPreferences

Using the code

  1. Coordinate system: The coordinates are specified in the user space:
    • The origin is located at the bottom-left corner of the page;
    • X axis extends from left to right and Y axis from bottom to top;
    • The length unit can be set using Page.UserUnit, and the default value is 1/72 inch.
  2. Fonts and XObjects can't be used directly. They need to be added to the document's resource dictionary and each of them should be associated with a key, and then used in the page content.

The following example shows a basic usage of this library:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using AnotherPDFLib;
using AnotherPDFLib.PdfObjects;
using AnotherPDFLib.PdfText;
using AnotherPDFLib.PdfGraphics;
 
namespace AnotherPDFLibTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        PdfDocument pdfdoc;
        PdfPage page;
        string PageNumberFormat;

        private void buttonCreateDocument_Click(object sender, EventArgs e)
        {
            pdfdoc = new PdfDocument(PaperSize.A4);
            pdfdoc.DocumentInfo.Creator = Application.ExecutablePath;
            pdfdoc.DocumentInfo.Author = "Liu Junfeng";
            pdfdoc.Catalog.PageMode = PageMode.UseOutlines;

            PageLabelRange firstrange = 
                new PageLabelRange(0, NumberingStyle.RomanLowercase);
            PageLabelRange secondrange = 
                new PageLabelRange(3, NumberingStyle.ArabicDecimal);
            pdfdoc.PageLabels.Add(firstrange);
            pdfdoc.PageLabels.Add(secondrange);

            comboBoxFont.Items.Clear();
            AddFont(StandardFont.Courier);
            AddFont(StandardFont.Helvetica);
            AddFont(ChineseFont.AdobeSong);

            buttonNewPage_Click(null, null);

            numericUpDownX.Maximum = (decimal)pdfdoc.PageSize.Width;
            numericUpDownY.Maximum = (decimal)pdfdoc.PageSize.Height;
            numericUpDownX.Value = 100;
            numericUpDownY.Value = numericUpDownY.Maximum - 100;
        }

        void AddFont(PdfFont font)
        {
            string fontID = pdfdoc.AddFont(font);
            string fontItem = 
              fontID + "(" + font.BaseFont + ")";
            comboBoxFont.Items.Add(fontItem);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            PageNumberFormat = this.Text + " (Page {0})";
            comboBoxEncoding.Items.AddRange(
                new object[] 
                    { "ASCII", "GB2312", "GB18030", "UTF-16BE" });
            comboBoxEncoding.SelectedIndex = 0;

            //set PdfWriter formattings
            PdfWriter.ListDictionary = false;
            PdfWriter.ListContentStream = true;
        }

        private void comboBoxEncoding_SelectedIndexChanged(
                                       object sender, EventArgs e)
        {
            switch (comboBoxEncoding.SelectedItem.ToString())
            {
                case "ASCII":
                    break;
                case "GB2312":
                    ChineseFont.AdobeSong.Encoding = 
                         CMap.ChineseSimplified.GB_EUC_H;
                    break;
                case "GB18030":
                    ChineseFont.AdobeSong.Encoding = 
                         CMap.ChineseSimplified.GBK_EUC_H;
                    break;
                default:
                    ChineseFont.AdobeSong.Encoding = 
                         CMap.ChineseSimplified.UniGB_UTF16_H;
                    break;
            }
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            try
            {
                string file = textBoxFile.Text;
                pdfdoc.Save(file);
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }
        private void buttonNewPage_Click(object sender, EventArgs e)
        {
            if (pdfdoc == null)
            {
                MessageBox.Show("Document not created!");
                return;
            }
            page = pdfdoc.NewPage();
            
            //add outline item
            PdfOutlineItem outlineitem = new PdfOutlineItem();
            outlineitem.Title = "Page " + pdfdoc.PageCount;
            outlineitem.Dest = Destination.FitPage(page);
            pdfdoc.Outlines.Append(outlineitem);

            TextState ts = new TextState();
            //set page level TextState
            //...
            //page.Content.AddGraphicObject(ts);
            ShowPageNumber();
        }

 

        void ShowPageNumber()
        {
            this.Text = string.Format(PageNumberFormat, pdfdoc.PageCount);
        }

        private void buttonAddText_Click(object sender, EventArgs e)
        {
            if (pdfdoc == null)
            {
                MessageBox.Show("Document not created!");
                return;
            }
            if (comboBoxFont.SelectedIndex == -1)
            {
                MessageBox.Show("No font selected!");
                return;
            }
            double tx = (double)numericUpDownX.Value;
            double ty = (double)numericUpDownY.Value;
            string font = 
                comboBoxFont.SelectedItem.ToString().Split('(')[0];
            int size = (int)numericUpDownSize.Value;
            Encoding encoding = 
                Encoding.GetEncoding(comboBoxEncoding.Text);

            PdfText pdfText = new PdfText(encoding);
            pdfText.Begin();
            pdfText.TextState.Font = new TextFont(font, size);
            pdfText.TextState.RenderingMode = GetRenderMode();
            pdfText.TextState.LineHeight = (int)size * 1.5;
            pdfText.StartNewLine(tx, ty);
            //pdfText.TextMatrix = TMatrix.Translation(tx, ty);
            foreach (string line in richTextBox.Lines)
            {
                pdfText.ShowText(line);
                pdfText.StartNewLine();
            }
            pdfText.End();
            page.Content.Add(pdfText);
        }

        RenderMode GetRenderMode()
        {
            RenderMode mode = RenderMode.None;
            if (checkBoxFill.Checked)
            {
                mode &= RenderMode.Fill;
            }
            if (checkBoxStroke.Checked)
            {
                mode &= RenderMode.Stroke;
            }
            if (checkBoxClipPath.Checked)
            {
                mode &= RenderMode.ClipPath;
            }
            return mode;
        }

        private void buttonnDrawGraph_Click(object sender, EventArgs e)
        {
            Path path = new Path();
            //SubPath subpath = new SubPath(0, 0);
            //subpath.AddLine(200, 300);
            //path.AddSubPath(subpath);
            //path.AddRectangle(200, 300, 100, 100);
            SubPath subpath = new SubPath(120, 800);
            subpath.LineTo(225, 700);
            subpath.LineTo(330, 800);
            path.AddSubPath(subpath);
            path.AddRectangle(100, 500, 250, 200);
            path.AddRectangle(120, 520, 210, 160);
            path.Stroke();

            page.Content.Add(path);

            Template.FilledSquare.Matrix = TMatrix.Scale(0.05, 0.01);
            Template.FilledTriangle.Matrix = TMatrix.Scale(0.02, 0.02);
            string square = pdfdoc.AddXObject(Template.FilledSquare);
            string triangle = pdfdoc.AddXObject(Template.FilledTriangle);
            page.Content.GraphicsState.Push();
            page.Content.GraphicsState.CTM = TMatrix.Translation(200, 550);
            page.Content.PaintXObject(square);
            page.Content.GraphicsState.CTM = TMatrix.Translation(-30, 50);
            page.Content.PaintXObject(triangle);
            page.Content.GraphicsState.CTM = TMatrix.Translation(90, 0);
            page.Content.PaintXObject(triangle);
            page.Content.GraphicsState.Pop();
        }

        private void buttonRemovePage_Click(object sender, EventArgs e)
        {
            pdfdoc.PageTree.Kids.Items.Remove(page);
            pdfdoc.PdfObjects.Remove(page.Identifier);
            pdfdoc.PdfObjects.Remove(page.Content.Identifier);

            ShowPageNumber();
        }

        private void buttonRotatePage_Click(object sender, EventArgs e)
        {
            page.Rotate += 90;
        }
    }
}

Template.FilledSquare and Template.FilledTriangle are defined as FormXOjbects:

public class Template
{
  static FormXObject square;
  public static FormXObject FilledSquare
  {
    get
    {
        if (square == null)
        {
            square = new FormXObject();
            square.BoundingBox = new PdfRectangle(0, 0, 1000, 1000);
            Path path = new Path();
            path.AddRectangle(0,0,1000,1000);
            path.Fill();


            square.Content.Add(path);
        }
        return square;
    }
  }

  static FormXObject triangle;
  public static FormXObject FilledTriangle
  {
    get
    {
        if (triangle == null)
        {
            triangle = new FormXObject();
            triangle.BoundingBox = 
                 new PdfRectangle(0, 0, 1000, 1000);



            SubPath subpath = new SubPath(0, 0);
            subpath.LineTo(500, 1000);
            subpath.LineTo(1000, 0);
            subpath.Close();
            Path path = new Path();
            path.Add(subpath);
            path.Fill();
            triangle.Content.Add(path);
        }
        return triangle;
    }
  }

The sample output

ToDo's

  • Color space and color values
  • Insert images
  • TrueType font
  • Annotations
  • Stream filters
  • ...

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Liu Junfeng
Software Developer (Senior) Beyondsoft SH
China China
No Biography provided

You may also be interested in...

Comments and Discussions

 
GeneralNot to be confused with PDFLib by PDFLib GmbH Pin
Oskar Austegard30-Jan-09 10:09
memberOskar Austegard30-Jan-09 10:09 
Generalyou should learn from iTextSharp to support true type font Pin
Unruled Boy7-Jan-09 3:08
memberUnruled Boy7-Jan-09 3:08 
Questionform filling functions? Pin
Jerry Y9-Feb-06 9:34
memberJerry Y9-Feb-06 9:34 
AnswerRe: form filling functions? Pin
Liu Junfeng12-Feb-06 21:03
memberLiu Junfeng12-Feb-06 21:03 
GeneralRe: form filling functions? Pin
Jerry Y14-Feb-06 7:25
memberJerry Y14-Feb-06 7:25 
GeneralSourceforge Project started! Pin
Liu Junfeng5-Jan-06 15:49
memberLiu Junfeng5-Jan-06 15:49 
GeneralRe: Sourceforge Project started! Pin
NewbieDude30-Jan-06 20:19
memberNewbieDude30-Jan-06 20:19 
GeneralNo source, then not an article Pin
zaf4-Jan-06 23:44
memberzaf4-Jan-06 23:44 
GeneralFonts / Samples Pin
gxdata4-Jan-06 18:54
membergxdata4-Jan-06 18:54 
GeneralRe: Fonts / Samples Pin
Liu Junfeng4-Jan-06 19:41
memberLiu Junfeng4-Jan-06 19:41 
QuestionSourceforge ?? Pin
guigros4-Jan-06 4:05
memberguigros4-Jan-06 4:05 
AnswerRe: Sourceforge ?? Pin
Liu Junfeng4-Jan-06 19:55
memberLiu Junfeng4-Jan-06 19:55 
GeneralRe: Sourceforge ?? Pin
chancipher8-May-06 17:32
memberchancipher8-May-06 17:32 
Questionwhere is AnotherPDFLib.dll source? Pin
moonxp29-Dec-05 14:50
membermoonxp29-Dec-05 14:50 
AnswerRe: where is AnotherPDFLib.dll source? Pin
Liu Junfeng30-Dec-05 18:10
memberLiu Junfeng30-Dec-05 18:10 
GeneralRe: where is AnotherPDFLib.dll source? Pin
André Ziegler5-Jan-06 11:15
memberAndré Ziegler5-Jan-06 11:15 
Questionhow to build a project that runs in a specifics user Pin
it4all27-Dec-05 5:13
memberit4all27-Dec-05 5:13 
AnswerRe: how to build a project that runs in a specifics user Pin
Liu Junfeng30-Dec-05 18:06
memberLiu Junfeng30-Dec-05 18:06 
AnswerRe: how to build a project that runs in a specifics user Pin
Bin Liu3-Jan-06 22:42
memberBin Liu3-Jan-06 22:42 
GeneralFile not Found Pin
htukor26-Dec-05 22:05
memberhtukor26-Dec-05 22:05 
GeneralRe: File not Found Pin
Liu Junfeng26-Dec-05 22:46
memberLiu Junfeng26-Dec-05 22:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160811.3 | Last Updated 4 Jan 2006
Article Copyright 2005 by Liu Junfeng
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid