iTextSharp - 并非所有字符都以 Helvetica 字体显示
iTextSharp - not all characters present in Helvetica font
我有一些包含 Omega 字符 (0x3A9) 的文本,当我以默认的 Helvetica 字体显示此字符时,PDF 中没有显示任何内容。
我正在使用
创建我的字体
BaseFont Helvetica = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
并且,正如预期的那样,Helvetica.CharExists(0x3A9) returns false。
我还为 TIMES_ROMAN、SYMBOL 和 ZAPF_DINGBATS 字体调用了 CharExists(0x3A9)。全部 return 错误。
- 我创建的字体不正确吗?有没有更好的方法来创建包含 omega 字符的字体?
- 有没有通用的方法来处理像这样丢失的字符?我是否应该枚举所有可用字体,直到找到 CharExists(0x3A9) returns true 的字体?
我的文档是英文的,但有一些特殊字符 - plus/minus、左右双引号、微米等
p.s。我看到我可以创建 Arial 字体:
BaseFont arial = BaseFont.CreateFont("c:\windows\fonts\arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
并且确实包含字符 0x3A9 的字形。但显然我无法使用 IDENTITY_H 编码创建 HELVETICA 字体。
我最终得到的东西有点复杂,但看起来很可靠。每次我将文本添加到我的文档时(到目前为止我只是通过简单地创建一个新短语来完成),我首先枚举字符串中的每个字符并调用 BaseFont.CharExists()。如果任何字符的答案都是假的,我会根据 CharExists() 的连续序列是真还是假将文本分成块。然后,对于存在于 Helvetica 中的块,我在 Helvetica 中创建了一个块,而其他的我在 Arial 中创建了一个块,然后 assemble 将这些块放入我的短语中。
我这样做的原因(这对大多数读者来说可能是显而易见的,但以防万一)是我不想总是将 Arial 字体添加到我的 PDF 文件中(以减小大小),并且我 95% 的文档不包含像 Omega 这样需要 Arial 的字符。这样,我只将 Arial 字体添加到真正需要它的那几个文档中。
Phrase phrase = null;
string s = "";
for (int i = 0 ; i < text.Length ; i++)
{
char c = text[i];
if (fonts.Regular.BaseFont.CharExists(c))
s += c; // Accumulate Helvetica characters in 's'
else
{
// Try adding the Arial font
iTextSharp.text.Font arial = fonts.Arial; // Creates the Arial font and adds it to the document if not already there
if (arial == null)
{
Debug.WriteLine(" Arial font not found");
s += c;
}
else if (!arial.BaseFont.CharExists(c))
{
Debug.WriteLine(" Arial does not contain the required glyph");
s += c;
}
else
{
// We have a character that Helvetica doesn't have, that Arial does
if (phrase == null)
{
// This is the first time we've realize that we need a split phrase
if (s.Length > 0)
{
// There was Helvetica text before the Arial character.
phrase = new Phrase(s, fonts.Regular);
// This code assumes that non-Helvetica characters generally come singly
phrase.Add(new Chunk(c, arial));
s = "";
}
else
{
// The Arial character is the first one in the string
phrase = new Phrase(new Chunk(c, arial));
}
}
else
{
// This is not the first Arial character in the string
if (s != "")
{
// There were Helvetica characters before this Arial character
phrase.Add(new Chunk(s, fonts.Regular);
s = "";
}
phrase.Add(new Chunk(c, arial));
}
}
}
}
if (phrase == null)
{
// We did not encounter any Arial characters, create a simple Phrase
phrase = new Phrase(text, fonts.Regular);
}
else if (s.Length > 0)
{
// There were Helvetica characters at the end of the string, add them now
phrase.Add(new Chunk(s, fonts.Regular));
}
我有一些包含 Omega 字符 (0x3A9) 的文本,当我以默认的 Helvetica 字体显示此字符时,PDF 中没有显示任何内容。
我正在使用
创建我的字体BaseFont Helvetica = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
并且,正如预期的那样,Helvetica.CharExists(0x3A9) returns false。
我还为 TIMES_ROMAN、SYMBOL 和 ZAPF_DINGBATS 字体调用了 CharExists(0x3A9)。全部 return 错误。
- 我创建的字体不正确吗?有没有更好的方法来创建包含 omega 字符的字体?
- 有没有通用的方法来处理像这样丢失的字符?我是否应该枚举所有可用字体,直到找到 CharExists(0x3A9) returns true 的字体?
我的文档是英文的,但有一些特殊字符 - plus/minus、左右双引号、微米等
p.s。我看到我可以创建 Arial 字体:
BaseFont arial = BaseFont.CreateFont("c:\windows\fonts\arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
并且确实包含字符 0x3A9 的字形。但显然我无法使用 IDENTITY_H 编码创建 HELVETICA 字体。
我最终得到的东西有点复杂,但看起来很可靠。每次我将文本添加到我的文档时(到目前为止我只是通过简单地创建一个新短语来完成),我首先枚举字符串中的每个字符并调用 BaseFont.CharExists()。如果任何字符的答案都是假的,我会根据 CharExists() 的连续序列是真还是假将文本分成块。然后,对于存在于 Helvetica 中的块,我在 Helvetica 中创建了一个块,而其他的我在 Arial 中创建了一个块,然后 assemble 将这些块放入我的短语中。
我这样做的原因(这对大多数读者来说可能是显而易见的,但以防万一)是我不想总是将 Arial 字体添加到我的 PDF 文件中(以减小大小),并且我 95% 的文档不包含像 Omega 这样需要 Arial 的字符。这样,我只将 Arial 字体添加到真正需要它的那几个文档中。
Phrase phrase = null;
string s = "";
for (int i = 0 ; i < text.Length ; i++)
{
char c = text[i];
if (fonts.Regular.BaseFont.CharExists(c))
s += c; // Accumulate Helvetica characters in 's'
else
{
// Try adding the Arial font
iTextSharp.text.Font arial = fonts.Arial; // Creates the Arial font and adds it to the document if not already there
if (arial == null)
{
Debug.WriteLine(" Arial font not found");
s += c;
}
else if (!arial.BaseFont.CharExists(c))
{
Debug.WriteLine(" Arial does not contain the required glyph");
s += c;
}
else
{
// We have a character that Helvetica doesn't have, that Arial does
if (phrase == null)
{
// This is the first time we've realize that we need a split phrase
if (s.Length > 0)
{
// There was Helvetica text before the Arial character.
phrase = new Phrase(s, fonts.Regular);
// This code assumes that non-Helvetica characters generally come singly
phrase.Add(new Chunk(c, arial));
s = "";
}
else
{
// The Arial character is the first one in the string
phrase = new Phrase(new Chunk(c, arial));
}
}
else
{
// This is not the first Arial character in the string
if (s != "")
{
// There were Helvetica characters before this Arial character
phrase.Add(new Chunk(s, fonts.Regular);
s = "";
}
phrase.Add(new Chunk(c, arial));
}
}
}
}
if (phrase == null)
{
// We did not encounter any Arial characters, create a simple Phrase
phrase = new Phrase(text, fonts.Regular);
}
else if (s.Length > 0)
{
// There were Helvetica characters at the end of the string, add them now
phrase.Add(new Chunk(s, fonts.Regular));
}