-
Notifications
You must be signed in to change notification settings - Fork 305
Expand file tree
/
Copy pathPdfFontResource.cs
More file actions
139 lines (133 loc) · 6.09 KB
/
PdfFontResource.cs
File metadata and controls
139 lines (133 loc) · 6.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*************************************************************************************************
Required Notice: Copyright (C) EPPlus Software AB.
This software is licensed under PolyForm Noncommercial License 1.0.0
and may only be used for noncommercial purposes
https://polyformproject.org/licenses/noncommercial/1.0.0/
A commercial license to use this software can be purchased at https://epplussoftware.com
*************************************************************************************************
Date Author Change
*************************************************************************************************
27/11/2025 EPPlus Software AB EPPlus 9
*************************************************************************************************/
using EPPlus.Export.Pdf.PdfObjects.PdfFonts;
using EPPlus.Export.Pdf.PdfSettings;
using EPPlus.Fonts.OpenType;
using EPPlus.Fonts.OpenType.Tables.Os2;
using System;
using System.Collections.Generic;
using EPPlus.Graphics;
using OfficeOpenXml.Interfaces.Fonts;
namespace EPPlus.Export.Pdf.PdfResources
{
internal class PdfFontResource : PdfResource
{
internal string fontName;
internal int fontObjectNumber = -1;
internal int descObjectNumber = -1;
internal int widthObjectNumber = -1;
internal OpenTypeFont fontData;
private int firstChar = 32;
private int lastChar = 255;
public PdfFontResource(string fontName, FontSubFamily subFamily, int labelNumber, PdfPageSettings pageSettings)
: base("F", labelNumber)
{
this.fontName = fontName;
fontData = OpenTypeFonts.LoadFont(fontName, subFamily, pageSettings.FontDirectories, pageSettings.SearchSystemDirectories);
}
//Get the Font Descriptor object to write in PDF.
internal PdfFontDescriptor GetFontDescriptorObject(int objectNumber, int version = 0)
{
int flag = 0;
if (fontData.PostTable.isFixedPitch != 0)
flag |= 1;
if (fontData.GetEnglishFontFamilyName().ToLower().Contains("serif"))
flag |= 1 << 1;
bool isSymbolic = false;
foreach (var sub in fontData.CmapTable.EncodingRecords)
{
if (sub.PlatformId == Fonts.OpenType.Tables.Cmap.Platforms.Windows)
{
if (sub.EncodingId == 0)
{
isSymbolic = true;
break;
}
if (sub.EncodingId == 1 || sub.EncodingId == 10)
{
isSymbolic = false;
break;
}
}
if (sub.PlatformId == Fonts.OpenType.Tables.Cmap.Platforms.Macintosh || sub.PlatformId == Fonts.OpenType.Tables.Cmap.Platforms.Unicode)
{
isSymbolic = true;
break;
}
}
if (isSymbolic)
flag |= 1 << 2; // Symbolic
else
flag |= 1 << 5; // Nonsymbolic
if (fontData.GetEnglishFontFamilyName().ToLower().Contains("script") || fontData.GetEnglishFontFamilyName().ToLower().Contains("cursive"))
flag |= 1 << 3;
if (fontData.PostTable.italicAngle.RawValue != 0 || (fontData.Os2Table.fsSelection & Os2Table.FsSelectionFlags.Italic) != 0)
flag |= 1 << 6;
if (((ushort)fontData.Os2Table.fsSelection & 0x100) != 0)
flag |= 1 << 16;
if (((ushort)fontData.Os2Table.fsSelection & 0x200) != 0)
flag |= 1 << 17;
if (((ushort)fontData.Os2Table.fsSelection & 0x400) != 0)
flag |= 1 << 18;
var fontBBox = new Rect();
fontBBox.X = fontData.HeadTable.Xmin;
fontBBox.Y = fontData.HeadTable.Ymin;
fontBBox.Width = fontData.HeadTable.Xmax;
fontBBox.Height = fontData.HeadTable.Ymax;
descObjectNumber = objectNumber;
return new PdfFontDescriptor
(
objectNumber,
fontName,
flag,
fontBBox,
Convert.ToDouble(fontData.PostTable.italicAngle.FloatValue),
fontData.Os2Table.sTypoAscender,
fontData.Os2Table.sTypoDescender,
0,
fontData.Os2Table.sCapHeight,
version
);
}
//Get the Widths object to write in PDF.
internal PdfFontWidths GetWidthsObject(int objectNumber, int version = 0)
{
List<int> widths = new List<int>();
int fallbackWidth = fontData.Os2Table.xAvgCharWidth;
var glyphMappings = fontData.CmapTable.GetPreferredSubtable().GetGlyphMappings();
for (int c = firstChar; c <= lastChar; c++)
{
var gi = glyphMappings.GetGlyphIndex((char)c);
if (gi == 0 && c != 0)
{
int normalizedWidth = (int)System.Math.Round(fallbackWidth / (double)fontData.HeadTable.UnitsPerEm * 1000);
widths.Add(normalizedWidth);
}
else
{
var hhMetric = fontData.HmtxTable.hMetrics[gi ?? 0];
var advanceWidth = Convert.ToInt16(hhMetric.advanceWidth);
int normalizedWidth = (int)System.Math.Round(advanceWidth / (double)fontData.HeadTable.UnitsPerEm * 1000);
widths.Add(normalizedWidth);
}
}
widthObjectNumber = objectNumber;
return new PdfFontWidths(objectNumber, widths, version);
}
//Get the Font Object to write in PDF.
internal PdfFont GetFontObject(int objectNumber, int version = 0)
{
fontObjectNumber = objectNumber;
return new PdfFont(objectNumber, fontName, PdfFontSubType.Type1, firstChar, lastChar, widthObjectNumber, descObjectNumber, PdfFontEncoding.WinAnsiEncoding);
}
}
}