gpt4 book ai didi

c# - iTextSharp 重用嵌入在 Acrofield 中的字体

转载 作者:太空狗 更新时间:2023-10-30 01:36:26 26 4
gpt4 key购买 nike

“iText In Action”中有一些技巧,涵盖了设置字体以及“FontFactory.RegisterDirectories”方法(正如书中所说...这是一个昂贵的调用)。但是,就我而言,我想用于新字段的字体已经嵌入到文档中(在现有的 Acrofield 中)。不能保证相同的字体将存在于用户的机器上(或网络服务器上)......有没有办法可以注册已经嵌入的字体,以便我可以将它重新用于其他对象?在下面的代码中,Acrofield“TheFieldIWantTheFontFrom”具有我想要重新用于名为“my_new_field”的字段的字体。任何帮助将不胜感激!

        using (MemoryStream output = new MemoryStream())
{

// Use iTextSharp PDF Reader, to get the fields and send to the
//Stamper to set the fields in the document
PdfReader pdfReader = new PdfReader(@"C:\MadScience\MSE_030414.pdf");

// Initialize Stamper (ms is a MemoryStream object)
PdfStamper pdfStamper = new PdfStamper(pdfReader, output);

// Get Reference to PDF Document Fields
AcroFields pdfFormFields = pdfStamper.AcroFields;

//*** CODE THAT HAVE NOT YET BEEN ABLE TO MAKE USE OF TO ASSIST WITH MY FONT ISSUE
//*** MIGHT BE HELP?
//List<object[]> fonts = BaseFont.GetDocumentFonts(pdfReader);
//BaseFont[] baseFonts = new BaseFont[fonts.Count];
//string[] fn = new string[fonts.Count];
//for (int i = 0; i < fonts.Count; i++)
//{
// Object[] obj = (Object[])fonts[i];
// baseFonts[i] = BaseFont.CreateFont((PRIndirectReference)(obj[1]));
// fn[i] = baseFonts[i].PostscriptFontName.ToString();
// //Console.WriteLine(baseFonts[i].FamilyFontName[0][1].ToString());
// //FontFactory.RegisteredFonts.Add(fn[i]);
// //FontFactory.Register(
// Console.WriteLine(fn[i]);
//}

//ICollection<string> registeredFonts = iTextSharp.text.FontFactory.RegisteredFonts;

//foreach (string s in registeredFonts)
//{
// Console.WriteLine("pre-registered: " + s);
//}

if (!FontFactory.Contains("georgia-bold"))
{
FontFactory.RegisterDirectories();
Console.WriteLine("had to register everything"); }

//registeredFonts = iTextSharp.text.FontFactory.RegisteredFonts;

//foreach (string s in registeredFonts)
//{
// Console.WriteLine("post-registered: " + s);
//}

Font myfont = FontFactory.GetFont("georgia-bold");

string nameOfField = "my_field";

AcroFields.Item fld = pdfFormFields.GetFieldItem(nameOfField);

//set the text of the form field
pdfFormFields.SetField(nameOfField, "test stuff");

pdfFormFields.SetField("TheFieldIWantTheFontFrom", "test more stuff");

bool madeit = pdfFormFields.SetFieldProperty(nameOfField, "textfont", myfont.BaseFont, null);

bool madeit2 = pdfFormFields.SetFieldProperty(nameOfField, "textsize", 8f, null);

pdfFormFields.RegenerateField(nameOfField);

// Set the flattening flag to false, so the document can continue to be edited
pdfStamper.FormFlattening = true;

// close the pdf stamper
pdfStamper.Close();

//get the bytes from the MemoryStream
byte[] content = output.ToArray();

using (FileStream fs = File.Create(@"C:\MadScience\MSE_Results.pdf"))
{
//byte[] b = outList[i];
fs.Write(content, 0, (int)content.Length);
fs.Flush();
}

}

最佳答案

是的,您可以重复使用字体,而且 PDF 规范实际上鼓励这样做。但是,您应该记住,某些字体可能仅作为子集嵌入。

以下代码改编自this post (小心,该网站有时会有讨厌的弹出窗口)。有关详细信息,请参阅代码中的注释。此代码针对 iTextSharp 5.4.4 进行了测试。

/// <summary>
/// Look for the given font name (not file name) in the supplied PdfReader's AcroForm dictionary.
/// </summary>
/// <param name="reader">An open PdfReader to search for fonts in.</param>
/// <param name="fontName">The font's name as listed in the PDF.</param>
/// <returns>A BaseFont object if the font is found or null.</returns>
static BaseFont findFontInForm(PdfReader reader, String fontName) {
//Get the document's acroform dictionary
PdfDictionary acroForm = (PdfDictionary)PdfReader.GetPdfObject(reader.Catalog.Get(PdfName.ACROFORM));

//Bail if there isn't one
if (acroForm == null) {
return null;
}

//Get the resource dictionary
var DR = acroForm.GetAsDict(PdfName.DR);

//Get the font dictionary (required per spec)
var FONT = DR.GetAsDict(PdfName.FONT);

//Look for the actual font and return it
return findFontInFontDict(FONT, fontName);
}

/// <summary>
/// Helper method to look at a specific font dictionary for a given font string.
/// </summary>
/// <remarks>
/// This method is a helper method and should not be called directly without knowledge of
/// the internals of the PDF spec.
/// </remarks>
/// <param name="fontDict">A /FONT dictionary.</param>
/// <param name="fontName">Optional. The font's name as listed in the PDF. If not supplied then the first font found is returned.</param>
/// <returns>A BaseFont object if the font is found or null.</returns>
static BaseFont findFontInFontDict(PdfDictionary fontDict, string fontName) {
//This code is adapted from http://osdir.com/ml/java.lib.itext.general/2004-09/msg00018.html
foreach (var internalFontName in fontDict.Keys) {
var internalFontDict = (PdfDictionary)PdfReader.GetPdfObject(fontDict.Get(internalFontName));
var baseFontName = (PdfName)PdfReader.GetPdfObject(internalFontDict.Get(PdfName.BASEFONT));
//// compare names, ignoring the initial '/' in the baseFontName
if (fontName == null || baseFontName.ToString().IndexOf(fontName) == 1) {
var iRef = (PRIndirectReference)fontDict.GetAsIndirectObject(internalFontName);
if (iRef != null) {
return BaseFont.CreateFont(iRef);
}
}
}

return null;
}

这是运行它的测试代码。它首先创建一个带有嵌入字体的示例文档,然后基于该文档创建第二个文档并重新使用该字体。在您的代码中,您实际上需要事先知道您要搜索的字体名称是什么。如果您没有安装 ROCK.TTF (Rockwell),您需要选择一个不同的字体文件来运行它。

//Test file that we'll create with an embedded font
var file1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");

//Secondary file that we'll try to re-use the font above from
var file2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test2.pdf");

//Path to font file that we'd like to use
var fontFilePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "ROCK.TTF");

//Create a basefont object
var font = BaseFont.CreateFont(fontFilePath, BaseFont.WINANSI, true);

//Get the name that we're going to be searching for later on.
var searchForFontName = font.PostscriptFontName;

//Step #1 - Create sample document
//The below block creates a sample PDF file with an embedded font in an AcroForm, nothing too special
using (var fs = new FileStream(file1, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();

//Create our field, set the font and add it to the document
var tf = new TextField(writer, new iTextSharp.text.Rectangle(50, 50, 400, 150), "first-name");
tf.Font = font;
writer.AddAnnotation(tf.GetTextField());

doc.Close();
}
}
}

//Step #2 - Look for font
//This uses a stamper to draw on top of the existing PDF using a font already embedded
using (var fs = new FileStream(file2, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var reader = new PdfReader(file1)) {
using (var stamper = new PdfStamper(reader, fs)) {

//Try to get the font file
var f = findFontInForm(reader, searchForFontName);

//Make sure we found something
if (f != null) {

//Draw some text
var cb = stamper.GetOverContent(1);
cb.BeginText();
cb.MoveText(200, 400);
cb.SetFontAndSize(f, 72);
cb.ShowText("Hello!");
cb.EndText();
}
}
}
}

编辑

我对上面的findFontInFontDict方法做了一个小小的修改。第二个参数现在是可选的。如果为 null,则返回它在提供的字典中找到的第一个字体对象。此更改允许我介绍以下方法,该方法按名称查找特定字段并获取字体。

static BaseFont findFontByFieldName(PdfReader reader, String fieldName) {
//Get the document's acroform dictionary
PdfDictionary acroForm = (PdfDictionary)PdfReader.GetPdfObject(reader.Catalog.Get(PdfName.ACROFORM));

//Bail if there isn't one
if (acroForm == null) {
return null;
}

//Get the fields array
var FIELDS = acroForm.GetAsArray(PdfName.FIELDS);
if (FIELDS == null || FIELDS.Length == 0) {
return null;
}

//Loop through each field reference
foreach (var fieldIR in FIELDS) {
var field = (PdfDictionary)PdfReader.GetPdfObject(fieldIR);

//Check the field name against the supplied field name
if (field.GetAsString(PdfName.T).ToString() == fieldName) {

//Get the resource dictionary
var DR = acroForm.GetAsDict(PdfName.DR);

//Get the font dictionary (required per spec)
var FONT = DR.GetAsDict(PdfName.FONT);

return findFontInFontDict(FONT);
}
}

return null;
}

关于c# - iTextSharp 重用嵌入在 Acrofield 中的字体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22186014/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com