mirror of
https://github.com/wmjordan/PDFPatcher.git
synced 2026-10-18 21:52:34 +08:00
152 lines
4.2 KiB
C#
152 lines
4.2 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using iTextSharp.text.pdf;
|
|
|
|
namespace PDFPatcher.Model
|
|
{
|
|
sealed class FontInfo : CMapAwareDocumentFont
|
|
{
|
|
[Flags]
|
|
internal enum CjkFontType
|
|
{
|
|
Unknown,
|
|
CJK = 0x01,
|
|
Chinese = 0x02 + CJK,
|
|
Gb18030Chinese = 0x0100 + Chinese,
|
|
Big5Chinese = 0x0200 + Chinese,
|
|
Japanese = 0x04 + CJK,
|
|
Korean = 0x08 + CJK,
|
|
Unicode = 0x4000,
|
|
None = 0x8000
|
|
}
|
|
|
|
readonly static Encoding __GbkEncoding = System.Text.Encoding.GetEncoding("gbk");
|
|
readonly static PdfName[] __GbkEncodingNames = [new PdfName("GBK-EUC-H"), new PdfName("GBK-EUC-V"), new PdfName("GB-EUC-H"), new PdfName("GB-EUC-V"), PdfName.WIN_ANSI_ENCODING];
|
|
readonly static string[] __gbkFontNames = ["宋体", "黑体", "楷体_GB2312", "仿宋体", "仿宋_GB2312", "隶书", "幼圆"];
|
|
readonly static PdfName[] __IdentityEncodingNames = [new PdfName("Identity-H"), new PdfName("Identity-V")];
|
|
public const int DefaultDefaultWidth = 1000;
|
|
|
|
readonly PdfDictionary _Font;
|
|
PdfDictionary _FontDescriptor;
|
|
internal PdfDictionary FontDescriptor {
|
|
get {
|
|
if (_FontDescriptor == null) {
|
|
_FontDescriptor = _Font.Locate<PdfArray>(PdfName.DESCENDANTFONTS).Locate<PdfDictionary>(0).Locate<PdfDictionary>(PdfName.FONTDESCRIPTOR) ?? _Font.Locate<PdfDictionary>(PdfName.FONTDESCRIPTOR);
|
|
_FontDescriptor ??= new PdfDictionary();
|
|
}
|
|
return _FontDescriptor;
|
|
}
|
|
}
|
|
string _FontName;
|
|
internal string FontName {
|
|
get {
|
|
if (_FontName == null) {
|
|
string fn;
|
|
var f = FontDescriptor.GetAsName(PdfName.FONTNAME);
|
|
if (f != null) {
|
|
fn = PdfName.DecodeName(f.ToString());
|
|
}
|
|
else {
|
|
fn = PostscriptFontName;
|
|
var i = fn.LastIndexOf(',');
|
|
if (i != -1) {
|
|
fn = fn.Substring(0, i);
|
|
}
|
|
}
|
|
// 删除子集的名称
|
|
_FontName = PdfDocumentFont.RemoveSubsetPrefix(fn);
|
|
}
|
|
return _FontName;
|
|
}
|
|
}
|
|
|
|
CjkFontType _CjkFontType = CjkFontType.Unknown;
|
|
internal CjkFontType CjkType {
|
|
get {
|
|
if (_CjkFontType == CjkFontType.Unknown) {
|
|
InitCjkFontType();
|
|
}
|
|
return _CjkFontType;
|
|
}
|
|
}
|
|
|
|
int _DefaultWidth = -1;
|
|
public int DefaultWidth {
|
|
get {
|
|
if (_DefaultWidth == -1) {
|
|
var w = _Font.Locate<PdfNumber>(PdfName.DESCENDANTFONTS, 0, PdfName.DW);
|
|
_DefaultWidth = w == null ? DefaultDefaultWidth : w.IntValue;
|
|
}
|
|
return _DefaultWidth;
|
|
}
|
|
}
|
|
|
|
private void InitCjkFontType() {
|
|
if (_Font.Contains(PdfName.TOUNICODE)) {
|
|
_CjkFontType = CjkFontType.None;
|
|
return;
|
|
}
|
|
var encoding = _Font.GetAsName(PdfName.ENCODING);
|
|
var fn = FontName.ToUpperInvariant();
|
|
var c = __gbkFontNames.Contains(fn) || __GbkEncodingNames.Contains(encoding);
|
|
_CjkFontType = c ? CjkFontType.Chinese : CjkFontType.None;
|
|
if (_CjkFontType != CjkFontType.None) {
|
|
return;
|
|
}
|
|
c = __IdentityEncodingNames.Contains(encoding);
|
|
if (c) {
|
|
_CjkFontType = CjkFontType.Unicode;
|
|
}
|
|
}
|
|
|
|
readonly int _FontID = -1;
|
|
internal int FontID => _FontID;
|
|
|
|
public FontInfo(PdfDictionary font, int refNumber)
|
|
: base(font) {
|
|
_Font = font;
|
|
_FontID = refNumber;
|
|
}
|
|
public FontInfo(PRIndirectReference refFont) : base(refFont) {
|
|
_Font = (PdfDictionary)PdfReader.GetPdfObjectRelease(refFont);
|
|
_FontID = refFont.Number;
|
|
}
|
|
|
|
static byte[] __CidSlot = new byte[2];
|
|
internal int DecodeCidToUnicode(iTextSharp.text.pdf.fonts.cmaps.CMapCidUni cMap, int cid) {
|
|
string s;
|
|
if (AppContext.Encodings.TextEncoding != null) {
|
|
__CidSlot[0] = (byte)(cid >> 8);
|
|
__CidSlot[1] = (byte)cid;
|
|
s = AppContext.Encodings.TextEncoding.GetString(__CidSlot);
|
|
}
|
|
else if (cMap != null) {
|
|
return cMap.Lookup(cid);
|
|
}
|
|
else {
|
|
__CidSlot[0] = (byte)(cid >> 8);
|
|
__CidSlot[1] = (byte)cid;
|
|
s = Decode(__CidSlot, 0, 2);
|
|
}
|
|
if (s.Length == 0) {
|
|
return 0;
|
|
}
|
|
return s[0];
|
|
}
|
|
|
|
internal string DecodeTextBytes(byte[] bytes) {
|
|
if (AppContext.Encodings.TextEncoding != null) {
|
|
return AppContext.Encodings.TextEncoding.GetString(bytes);
|
|
}
|
|
if (CjkType == CjkFontType.Chinese) {
|
|
return __GbkEncoding.GetString(bytes);
|
|
}
|
|
return Decode(bytes, 0, bytes.Length);
|
|
}
|
|
internal string DecodeText(PdfString text) {
|
|
return DecodeTextBytes(text.GetBytes());
|
|
}
|
|
}
|
|
}
|