一项目中要生成pdf文件。而且文件中的文本,图像等需要绝对定位。
我是用iTextSharp来生成pdf的,经过几天的摸索熟悉,能差不多能达到预期目的了,只是在绝对定位中,不知如何指定粗体等字体样式。
了解这方面的朋友请帮帮忙。附代码:
Document doc = new Document(new iTextSharp.text.Rectangle(564, 351));
PdfWriter writer= PdfWriter.GetInstance(doc, new FileStream(HttpContext.Current.Server.MapPath("1.pdf"), FileMode.Create));
doc.Open();
PdfContentByte cb = writer.DirectContent;
cb.BeginText();
BaseFont bfont = BaseFont.CreateFont(@"c:\windows\fonts\SIMHEI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);//设定字体:黑体
cb.SetFontAndSize(bfont, 18);//设定字号
cb.SetCharacterSpacing(1);//设定字间距
cb.SetRGBColorFill(66, 00, 00);//设定文本颜色
cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "在位置100,70处开始显示文本", 100, 70,0);
cb.EndText();
doc.Close();
我是用iTextSharp来生成pdf的,经过几天的摸索熟悉,能差不多能达到预期目的了,只是在绝对定位中,不知如何指定粗体等字体样式。
了解这方面的朋友请帮帮忙。附代码:
Document doc = new Document(new iTextSharp.text.Rectangle(564, 351));
PdfWriter writer= PdfWriter.GetInstance(doc, new FileStream(HttpContext.Current.Server.MapPath("1.pdf"), FileMode.Create));
doc.Open();
PdfContentByte cb = writer.DirectContent;
cb.BeginText();
BaseFont bfont = BaseFont.CreateFont(@"c:\windows\fonts\SIMHEI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);//设定字体:黑体
cb.SetFontAndSize(bfont, 18);//设定字号
cb.SetCharacterSpacing(1);//设定字间距
cb.SetRGBColorFill(66, 00, 00);//设定文本颜色
cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "在位置100,70处开始显示文本", 100, 70,0);
cb.EndText();
doc.Close();
Phrase如何加入到ContentByte中呢?又是如何定位呢?
{
Font font = FontFactory.GetFont(strFontName, FontSize, FontStyle, TextColor);
return font;
} /// <summary>
/// 创建中文字体(实现中文)
/// </summary>
/// <returns></returns>
public static Font CreateChineseFont()
{
BaseFont.AddToResourceSearch(@"E:\临时存储文件夹\ASP.Net操作PDF文件\实现方法包\iTextAsian-1.0.dll");
BaseFont.AddToResourceSearch(@"E:\临时存储文件夹\ASP.Net操作PDF文件\实现方法包\iTextAsianCmaps-1.0.dll");
BaseFont baseFT = BaseFont.CreateFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
Font font = new Font(baseFT);
return font;
}
SetFontAndSize里的参数只能用BaseFont变量,无法用Font变量。
{
this.CheckWriter();
this.state.size = size;
this.state.fontDetails = this.writer.AddSimple(bf);
PageResources pageResources = this.PageResources;
PdfName fontName = this.state.fontDetails.FontName;
fontName = pageResources.AddFont(fontName, this.state.fontDetails.IndirectReference);
this.content.Append(fontName.GetBytes()).Append(' ').Append(size).Append(" Tf").Append_i(this.separator);
}
public override void SetFontAndSize(BaseFont bf, float size)
{
this.CheckWriter();
base.state.size = size;
if (bf.FontType == 4)
{
base.state.fontDetails = new FontDetails(null, ((DocumentFont) bf).IndirectReference, bf);
}
else
{
base.state.fontDetails = base.writer.AddSimple(bf);
}
PdfName fontName = stdFieldFontNames.get_Item(bf.PostscriptFontName);
if (fontName == null)
{
if (bf.Subset && (bf.FontType == 3))
{
fontName = base.state.fontDetails.FontName;
}
else
{
fontName = new PdfName(bf.PostscriptFontName);
base.state.fontDetails.Subset = false;
}
}
this.PageResources.AddFont(fontName, base.state.fontDetails.IndirectReference);
base.content.Append(fontName.GetBytes()).Append(' ').Append(size).Append(" Tf").Append_i(base.separator);
}
这本书去下载下来看看吧,不知道有没有中文的。
不过,上面那个原型里,好像没有看到有关FontStyle的,只有FontFamily和FontSize。
或者有没有其它办法来绝对定位。
Windows中一般都是使用TrueType字体,每个中文版Windows操作系统均默认安装了宋体、仿宋、黑体和楷体四种字体,你还可以安装其他第三方字体,如安装了Office 2000后,会自动安装华文行楷等字体,比较奇怪的是,在PDF文件中插入了一种本计算机才有的字体,在打开PDF文件的计算机上虽然没有该字体,但仍然能正常显示!这有别于Word文件,Word文件将当前计算机中没有的字体一律用宋体代替,这大概是意外收获吧。
字体文件一般保存在windir\Fonts目录中,扩展名为TTF,还有扩展名为TTC的字体文件,也是TrueType字体,不过是一个集合,也就是里面有多种字体。下面列出windows2000简体中文版四种标准字体的文件名称:
SIMSUN.TTC:宋体和新宋体
SIMKAI.TTF:楷体
SIMHEI.TTF:黑体
SIMFANG.TTF:仿宋体
TrueType字体应用
按下面的方法写入黑体字文字,大小为32磅:
BaseFont bfHei = BaseFont.createFont(@"c:\winnt\fonts\SIMHEI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
Font font = new Font(bfHei, 32);
String text = "这是黑体字测试!";
document.Add(new Paragraph(text, font));
不要管BaseFont.createFont方法第二、三个参数的意思,依葫芦画瓢就行了,第一个参数显示就是字体文件存放的位置。
后面的代码都非常好理解,不再赘述。
TruType字体集合的应用
字体集合的使用同上面差不多,只是在在createFont方中要指定使用哪种字体。如:
BaseFont bfSun=BaseFont.createFont(@"c:\winnt\fonts\SIMSUN.TTC,1", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
font = new Font(bfSun, 16);
text = "这是字体集合中的新宋体测试!";
document.Add(new Paragraph(text, font));
不难看出,在使用BaseFont.createFont方法时,第一个参数@"c:\winnt\fonts\SIMSUN.TTC,1"中多了一个“,1”,表示使用序号为1字体,序号为0的字体为宋体。
毕竟我们不是做排版软件,有了上面的办法就基本上够用了,真正很复杂的PDF文件制作,不妨做成XML文件(最简单的办法就是用Word排版,然后另存为web页了),然后按第七章的办法转换。
代码见示例代码0901。
第十章 图象和文本的绝对位置
pdfContentByte
到目前为止,我们已经使用了简单的iText,我们已经添加了文本、图片、段落、章节、列表、表格等,没有涉及到布局问题。Itext分割文本到每页中,并将每个单词、句子、段落布置到页面上,但有时我们并不需要这种自动格式,有时我们希望将一些图象或者文本放置在某页的指定位置,为实现该功能,我们将使用PdfContentByte类。
为代替第一章,仅用PdfWriter类的getInstance方法是不够的,你必须真实地拥有一个PdfWriter对象,你可以通过在使用Writer对象中使用getDirectContent()方来得到该对象。例:
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("test.pdf"));
PdfContentByte cb = writer.DirectContent;
说明:当你添加高级对象(如表格)时,两个PdfContentByte对象将被内部使用:一个用于文本,一个用用于图象(如边界或单元格背景)。文本绘制浮于图象的上面。
当你通过getDirectContent()方法直接使用PdfContentByte对象时,你所添加的所有对象都将浮于文本和图象。如果你想避免这种情况和希望添加内容在图象或文本的背后,你需要使用用getDirectContentUnder()方。
一句话,当一页完成时,4层的重叠遵照如下顺序:
1、 通过getDirectContentUnder()得到的PdfContentByte
2、 包含图象或高级对象的内部PdfContentByte
3、 病文本或高级对象的内部PdfContentByte
4、 通过getDirectContent()得到的PdfContentByte
简单图形
在示例代码1001中,绘制了一些简单图形,我们使用了诸如moveTo和lineTo方法来在移动到页面上当前位置然后画一条直线到其他位置。我们使用了诸如setLineWidth和setLineDash方法来改变直线的外观,如:
cb.LineWidth = 10f;
cb.moveTo(100, 700);
cb.lineTo(200, 800);
cb.stroke();
说明:当你改变诸如颜色、线宽等属性时,只有你在调用stroke方法时才起作用。在例中绘制三角形时,我们设置颜色为绿色,在使用stroke方法前我们改变颜色为红色,则绘制三角形的结果为为红色而不是绿色,该例中还有矩形、圆等使用方法。
文本
当你想将文本写入ContentByte中时,你必须使用方法beginText()和endText,你也必须设置字体和尺寸。就象图形示例中一样,还有许多方法用于写入和放置文本,但你最需要的是方法showTextAligned和方法showText配合setTextMatrix。
例1:
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); cb.beginText();
cb.setFontAndSize(bf, 12);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, text + "This text is centered", 250, 700, 0);
cb.endText();
例2:
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.beginText();
cb.setFontAndSize(bf, 12);
cb.setTextMatrix(100, 400);
cb.showText("Text at position 100,400.");
cb.endText();
请参见示例代码1002。
我用的是ItextSharp,没有找到实现绝对定位的方法
PdfPTable tbl = new PdfPTable(1);
Font font = iTextSharp.text.FontFactory.GetFont("Verdana, Arial, Helvetica, sans-serif", 14, Font.BOLD, new Color(255, 0, 0));
Phrase str = new Phrase("anything", font);
PdfPCell cell = new PdfPCell(str);
tbl.AddCell(cell);
cb.SaveState();
tbl.TotalWidth = doc.Right - doc.Left;
tbl.WriteSelectedRows(0, -1, doc.Left, doc.PageSize.Height - 30, cb);
cb.RestoreState();
代码如下:
Document doc = new Document(new iTextSharp.text.Rectangle(564, 351));
PdfWriter writer= PdfWriter.GetInstance(doc, new FileStream(HttpContext.Current.Server.MapPath("1.pdf"), FileMode.Create));
PdfContentByte cb = writer.DirectContent;
BaseFont kaiti = BaseFont.CreateFont(@"c:\windows\fonts\simkai.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
iTextSharp.text.Font font_b = new iTextSharp.text.Font(kaiti, 18, iTextSharp.text.Font.BOLD, iTextSharp.text.Color.BLUE);
Phrase ps_bold = new Phrase("中文单粗体测试", font_b);
ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, ps_bold, 155, 40, 0);
使用windows的字体仍不是个好办法。。
如果你的web系统在linus上运行怎么办?
因此,使用Phrase写粗体时,如果没有这个中文粗体,则使用粗笔刷,这时文字比较粗糙.
PdfContentByte也是同样道理.所以要想使用PdfContentByte实现粗体有两种方法:
1:设置粗笔刷,例子如下:
FPDFContentByte.beginText();
FPDFContentByte.setFontAndSize(bf, CellFont.Size);
if (Bold)
FPDFContentByte.TextRenderingMode = PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE;
else
FPDFContentByte.TextRenderingMode = PdfContentByte.TEXT_RENDER_MODE_FILL;
FPDFContentByte.setTextMatrix(x * Woodaxe.Enterprise.ConvertTool.Pixel2Point, y * Woodaxe.Enterprise.ConvertTool.Pixel2Point);
FPDFContentByte.showText(s);
FPDFContentByte.endText();