How can I use a bold version of Arial Unicode in iText?
I want to use the standard bold Arial font in iText, but I would like to default to Arial Unicode if a character doe开发者_JS百科s not exist as bold. Is there a way to combine fonts in iText? I have searched for a bold ttf file of Arial Unicode, but I have not been able to find one.
Fonts are normally drawn as "filled shapes". You can do a "poor man's bold" by adding a stroke of some width by changing the Text Render Mode.
And it looks like iText has already implemented this very feature (along with "poor man's italic", in PdfChunk.java. It uses a stroke width of 1/30 the font size.
So if you just ask for a bold version of Arial Unicode, you should get "poor man's bold" already.
As for combined fonts, I'm not aware of a system to do so, no. You could do something like that at a higher level by breaking up the chunks. Something like:
void addTextToPara(Paragraph paragraph, String string, Font font, Font otherFont) {
BaseFont mainfont = font.getBaseFont();
StringBuffer curChunk = new StringBuffer();
StringBuffer otherChunk = new StringBuffer();
for (int curCharIdx = 0; curCharIdx< string.length(); ++curCharIdx) {
char curChar = string.charAt(curCharIdx);
byte charBytes[] = mainFont.convertToBytes(curChar);
if (charBytes == null || charBytes.length == 0) {
// can't represent that character in the main font
if (curChunk.length() > 0) {
paragraph.add(new Chunk(curChunk.toString(), font);
curChunk.setLength(0);
}
otherChunk.append(curChar);
} else {
if (otherChunk.length() > 0) {
paragraph.add(new Chunk(otherChunk.toString(), otherFont);
otherChunk.setLength(0);
}
curChunk.append(curChar);
// can represent the character with the main font
}
}
if (curChunk.length() > 0) {
paragraph.add(new Chunk(curChunk.toString(), font);
} else if (otherChunk.length() > 0) {
paragraph.add(new Chunk(otherChunk.toString(), otherFont);
}
}
BaseFont arialBoldBaseFont = BaseFont.createFont(arialBoldPath, BaseFont.WINANSI, false); // not embedded
BaseFont arialUnicodeBaseFont = BaseFont.createFont(arialUniPath, BaseFont.IDENTITY_H, true); // IDENITY_H forces an embedded subset, ignores "embedded" param.
Font mainFont = new Font(arialBoldBaseFont, size);
Font backupFont = new Font(arialUnicodeBaseFont, size, Font.BOLD);
...
addTextToPara(paragraph, string, mainFont, backupFont);
Note that the above code doesn't attempt to see if a given char can be drawn in otherFont
. It's possible to rewrite addTextToPara()
to take an array of fonts, but I'm not nearly that bored. ;)
With the above code, you could create the BaseFonts with whatever encodings you like, I just prefer "Identity H" for 98% of the cases out there. mainFont
could be build from a WinAnsiEncoding
font, and backupFont
could be Something Else. Heck, you could even do something like:
BaseFont mainFont = BaseFont.createFont(arialBoldPath, BaseFont.WINANSI, false);
BaseFont backupFont = BaseFont.createFont(arialBoldPath, BaseFont.IDENTITY_H, true);
Use the same system-level font for both, and only embed the characters that fall outside "the norm". This still produces two separate font resources in the PDF, but one is not embedded (and used most of the time), and the other is an embedded subset of hopefully-rare characters.
精彩评论