2005年08月11日

今天在调试书签导入的时候发现SimpleBookmark.cs的一处bug(注意对比我红色字体标记部分):

源程序是:

 internal static Object[] IterateOutlines(PdfWriter writer, PdfIndirectReference parent, ArrayList kids, bool namedAsNames) {
            PdfIndirectReference[] refs = new PdfIndirectReference[kids.Count];
            for (int k = 0; k < refs.Length; ++k)
                refs[k] = writer.PdfIndirectReference;
            int ptr = 0;
            int count = 0;
            foreach (Hashtable map in kids) {
                ++ptr;
                Object[] lower = null;
                ArrayList subKid = (ArrayList)map["Kids"];
                if (subKid != null && subKid.Count > 0)
                    lower = IterateOutlines(writer, refs[ptr], subKid, namedAsNames);
                PdfDictionary outline = new PdfDictionary();
                ++count;
                if (lower != null) {
                    outline.Put(PdfName.FIRST, (PdfIndirectReference)lower[0]);
                    outline.Put(PdfName.LAST, (PdfIndirectReference)lower[1]);
                    int n = (int)lower[2];
                    if ("false".Equals(map["Open"])) {
                        outline.Put(PdfName.COUNT, new PdfNumber(-n));
                    }
                    else {
                        outline.Put(PdfName.COUNT, new PdfNumber(n));
                        count += n;
                    }
                }
                outline.Put(PdfName.PARENT, parent);
                if (ptr > 0)
                    outline.Put(PdfName.PREV, refs[ptr - 1]);
                if (ptr < refs.Length – 1)
                    outline.Put(PdfName.NEXT, refs[ptr + 1]);
                outline.Put(PdfName.TITLE, new PdfString((String)map["Title"], PdfObject.TEXT_UNICODE));
                String color = (String)map["Color"];
                if (color != null) {
                    try {
                        PdfArray arr = new PdfArray();
                        StringTokenizer tk = new StringTokenizer(color);
                        for (int k = 0; k < 3; ++k) {
                            float f = float.Parse(tk.NextToken(), System.Globalization.NumberFormatInfo.InvariantInfo);
                            if (f < 0) f = 0;
                            if (f > 1) f = 1;
                            arr.Add(new PdfNumber(f));
                        }
                        outline.Put(PdfName.C, arr);
                    } catch {} //in case it’s malformed
                }
                String style = (String)map["Style"];
                if (style != null) {
                    style = style.ToLower();
                    int bits = 0;
                    if (style.IndexOf("italic") >= 0)
                        bits |= 1;
                    if (style.IndexOf("bold") >= 0)
                        bits |= 2;
                    if (bits != 0)
                        outline.Put(PdfName.F, new PdfNumber(bits));
                }
                CreateOutlineAction(outline, map, writer, namedAsNames);
                writer.AddToBody(outline, refs[ptr]);//这里变成了从refs[1]到refs[refs.Lenght]了,结果自然而知了。
            }
            return new Object[]{refs[0], refs[refs.Length - 1], count};
        }

修改后的程序为:

 internal static Object[] IterateOutlines(PdfWriter writer, PdfIndirectReference parent, ArrayList kids, bool namedAsNames) {
            PdfIndirectReference[] refs = new PdfIndirectReference[kids.Count];
            for (int k = 0; k < refs.Length; ++k)
                refs[k] = writer.PdfIndirectReference;
            int ptr = 0;
            int count = 0;
            foreach (Hashtable map in kids) {                
                Object[] lower = null;
                ArrayList subKid = (ArrayList)map["Kids"];
                if (subKid != null && subKid.Count > 0)
                    lower = IterateOutlines(writer, refs[ptr], subKid, namedAsNames);
                PdfDictionary outline = new PdfDictionary();
                ++count;
                if (lower != null) {
                    outline.Put(PdfName.FIRST, (PdfIndirectReference)lower[0]);
                    outline.Put(PdfName.LAST, (PdfIndirectReference)lower[1]);
                    int n = (int)lower[2];
                    if ("false".Equals(map["Open"])) {
                        outline.Put(PdfName.COUNT, new PdfNumber(-n));
                    }
                    else {
                        outline.Put(PdfName.COUNT, new PdfNumber(n));
                        count += n;
                    }
                }
                outline.Put(PdfName.PARENT, parent);
                if (ptr > 0)
                    outline.Put(PdfName.PREV, refs[ptr - 1]);
                if (ptr < refs.Length – 1)
                    outline.Put(PdfName.NEXT, refs[ptr + 1]);
                outline.Put(PdfName.TITLE, new PdfString((String)map["Title"], PdfObject.TEXT_UNICODE));
                String color = (String)map["Color"];
                if (color != null) {
                    try {
                        PdfArray arr = new PdfArray();
                        StringTokenizer tk = new StringTokenizer(color);
                        for (int k = 0; k < 3; ++k) {
                            float f = float.Parse(tk.NextToken(), System.Globalization.NumberFormatInfo.InvariantInfo);
                            if (f < 0) f = 0;
                            if (f > 1) f = 1;
                            arr.Add(new PdfNumber(f));
                        }
                        outline.Put(PdfName.C, arr);
                    } catch {} //in case it’s malformed
                }
                String style = (String)map["Style"];
                if (style != null) {
                    style = style.ToLower();
                    int bits = 0;
                    if (style.IndexOf("italic") >= 0)
                        bits |= 1;
                    if (style.IndexOf("bold") >= 0)
                        bits |= 2;
                    if (bits != 0)
                        outline.Put(PdfName.F, new PdfNumber(bits));
                }
                CreateOutlineAction(outline, map, writer, namedAsNames);
                writer.AddToBody(outline, refs[ptr]);
                ++ptr;
            }
            return new Object[]{refs[0], refs[refs.Length - 1], count};
        }

2005年08月10日

http://soft.rubypdf.com/softwares/pdf-bookmark-extractor

About PDF Bookmark Extractor 1.0

从PDF中提取书签,然后存为xml或者txt,也可以在textBox中显示,需要Microsoft .Net Framework 1.1

Allows extract bookmarks(outlines) from a given PDF
and show it in textBox, save it as XML or txt format.
Supports unicode bookmarks.
Is Free software,any question and suggestion please contract:
steedsoft@gmail.com
http://www.steedsoft.com
http://blog.donews.com/rocsky
Thanks for iTextSharp

notice:
this software need Microsoft .Net Framework 1.1 support,you can get it from
http://download.microsoft.com/download/7/b/9/7b90644d-1af0-42b9-b76d-a2770319a568/dotnetfx.exe

2005年07月11日

iText由于其强大的功能和开源特性,而被广泛使用于各种project中,同时也有了各种port的版本。

1.iText的正式发布版本

http://www.lowagie.com/iText/(iText.sf.net)

2.iText的Early Access version(也许叫做测试版本吧)

http://itextpdf.sourceforge.net/

这个版本又包含了java1.1和java2两种版本,注意java1.1版本还需从该网站下载 Collection classes。

3.iTextDotNet,这个版本是利用J#编译的版本,使用的时候需要一下环境

  • Windows 98/2000/XP.
  • Microsoft .NET Framework 1.1
  • Microsoft Visual J# .NET Redistributable Package — http://msdn.microsoft.com/vjsharp/downloads/howtoget.asp
  • http://www.ujihara.jp/iTextdotNET/en/

    http://itextdotnet.sf.net

    4.iTextShparp:重新使用C#开发的版本,开发上和iText的java版本或者iTextdotnet版本区别比较大,中文支持仍是问题,namespace也不再和iText的其它版本保持一致,感觉移植iText的java程序或者iTextdotnet的程序比较麻烦,因为方法,实践,属性赋值都做了很大的改动。

    http://itextsharp.sf.net

    5.iText的GCJ版本,

    一个是pdftk:http://www.accesspdf.com/pdftk

    支持多种操作系统,GPL开源,CNI接口开发的命令行程序,拥有很多商业软件所具有的功能,可以说功能非常强大,但不提供对CJK的支持,这主要还是GCJ的问题。

    另外一个是我编译的一个版本,曾用它写过pdfsplit,pdfmerge,pdfencrypt,pdfdecrypt,pdfwatermark等程序,我喜欢使用java写程序,然后用GCJ来编译,因为我不懂C,也不想牵扯到那么多语言进来。当然我这个版本还可以编译更多的其它程序,这主要是看需要而定,当然中文支持的问题就暂时别考虑了。

    用gcj编译的目的,提高运行速度,抛开JVM(java的虚拟机)

    缺点,对awt,swing的支持非常有限,对CJK的支持非常有限。

    6.我的另外一个使用iKVM编译的版本,不需要Microsoft Visual J# .NET Redistributable Package ,另外应该可以使用在MONO的环境下(没有测试过呢)。

    对于iText的GCJ版本和IKVM版本,不知道是否有人愿意合作共同开发呢?

    很早以前曾介绍过如何用gcj编译iText,可惜文章随着空间的丢失也一并丢失了,相关的程序也没处下载,虽然我本机上还有,但也懒得上传了,因为类似的程序太多了。

    关于IKVM版本,我的blog上有些介绍。

    不知道还有没有遗漏的了?

    看到http://forum.planetpdf.com/一帖子寻找通过程序实现给PDF添加附件的方法,就好奇测试了下,用iText和iTextsharp编写成功,但iTextSharp对中文的支持有问题,还没有查出原因来。另外如何通过VB和Acrobat实现附件的添加还没有实现,不知道哪位高人可以指点一二?

    另附上iTextSharp版本的pdfattachfile:

    ftp://gmail.512j.com/friend/rocsky/soft/pdfattachfile.zip

    因为是demo的原因,只限制了附件为xls,至于位置,附件图标显示颜色,附件显示名称,附件描述等信息都没有做(代码写死了)。

    该程序需要微软的vs.net framework 1.1

    http://msdn.microsoft.com/netframework/downloads/framework1_1/

    程序实用SharpDevelop(#Develop)实现。


    2005年07月07日

    一个以java下iText类为基础用C#重写的类iTextSharp从2003的0.4版本到2005年5月一直没有更新,网站也没有任何说明,很多人都以为它已经停止开发了,今天在网上闲逛时竟然发现已经更新到了3.0.4版本,而且是连续release多个版本,看来一个让人期待的类再次激活了,值得庆幸。

    http://itextsharp.sourceforge.net/

    http://sourceforge.net/projects/itextsharp/

    http://switch.dl.sourceforge.net/sourceforge/itextsharp/itextsharp-3.0.4.zip

    http://switch.dl.sourceforge.net/sourceforge/itextsharp/itextsharp-3.0.4-dll.zip

    从代码结构上看,应该是与最新版本的iText基本上保持同步了。

    只可惜失业了,只能用家中的老爷车机器(2001年购买的C700+512M Ram)配上SharpDevelop来研究它了。