123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- #define USE_POSTSCRIPT_NAME
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- using System.IO;
- using FastReport.Export.TTF;
- using FastReport.Fonts;
- using System.Threading.Tasks;
- using System.Linq;
- namespace FastReport.Export.Pdf
- {
- public partial class PDFExport : ExportBase
- {
- private List<ExportTTFFont> fonts;
- private List<ExportTTFFont> pageFonts;
- private bool skipCurrentFont;
- private void AppendFont(StringBuilder Result, int fontNumber, float fontSize, Color fontColor)
- {
- if (!textInCurves)
- {
- ExportTTFFont pdffont = pageFonts[fontNumber];
- Result.Append(pdffont.Name).Append(" ").Append(FloatToString(fontSize)).AppendLine(" Tf");
- GetPDFFillColor(fontColor, Result);
- }
- }
- private void AppendFontAcroForm(StringBuilder Result, int fontNumber, float fontSize, Color fontColor)
- {
- ExportTTFFont pdffont = fonts[fontNumber];
- Result.Append(pdffont.Name).Append(" ").Append(FloatToString(fontSize)).AppendLine(" Tf");
- GetPDFFillColor(fontColor, Result);
- }
- private int GetObjFontNumber(Font font)
- {
- int i;
- for (i = 0; i < pageFonts.Count; i++)
- if (FontEquals(font, pageFonts[i].SourceFont))
- break;
- if (i < pageFonts.Count)
- return i;
- else
- {
- pageFonts.Add(GetGlobalFont(font));
- return pageFonts.Count - 1;
- }
- }
- private int GetObjFontNumberAcroForm(Font font)
- {
- int i;
- for (i = 0; i < fonts.Count; i++)
- if (FontEquals(font, fonts[i].SourceFont))
- break;
- if (i < fonts.Count)
- return i;
- else
- {
- GetGlobalFont(font);
- return fonts.Count - 1;
- }
- }
- private ExportTTFFont GetGlobalFont(Font font)
- {
- int i;
- for (i = 0; i < fonts.Count; i++)
- if (FontEquals(font, fonts[i].SourceFont))
- break;
- if (i < fonts.Count)
- return fonts[i];
- else
- {
- ExportTTFFont fontitem;
- fontitem = new ExportTTFFont(font);
- fontitem.FillOutlineTextMetrix();
- fontitem.FillEmulate();
- //// 20180604
- //bool his_italic = fontitem.TextMetric.otmItalicAngle != 0;
- //bool his_bold = fontitem.TextMetric.otmTextMetrics.tmWeight > 550;
- //if (font.Bold != his_bold)
- // fontitem.NeedSimulateBold = true;
- //if (font.Italic != his_italic)
- // fontitem.NeedSimulateItalic = true;
- fonts.Add(fontitem);
- fontitem.Name = "/F" + (fonts.Count - 1).ToString();
- return fontitem;
- }
- }
- private string GetToUnicode(ExportTTFFont pdfFont)
- {
- StringBuilder toUnicode = new StringBuilder(2048);
- toUnicode.AppendLine("/CIDInit /ProcSet findresource begin");
- toUnicode.AppendLine("12 dict begin");
- toUnicode.AppendLine("begincmap");
- toUnicode.AppendLine("/CIDSystemInfo");
- toUnicode.AppendLine("<< /Registry (Adobe)");
- toUnicode.AppendLine("/Ordering (UCS)");
- toUnicode.AppendLine("/Ordering (Identity)");
- toUnicode.AppendLine("/Supplement 0");
- toUnicode.AppendLine(">> def");
- toUnicode.Append("/CMapName /").Append(pdfFont.GetEnglishFontName().Replace(',', '+')).AppendLine(" def");
- toUnicode.AppendLine("/CMapType 2 def");
- toUnicode.AppendLine("1 begincodespacerange");
- toUnicode.AppendLine("<0000> <FFFF>");
- toUnicode.AppendLine("endcodespacerange");
- int charCount = 0;
- foreach (GlyphChar glyphChar in pdfFont.UsedGlyphChars)
- {
- if (glyphChar.GlyphType == GlyphType.Character ||
- glyphChar.GlyphType == GlyphType.None)
- charCount++;
- }
- int stringCount = 0;
- foreach (GlyphChar glyphChar in pdfFont.UsedGlyphChars)
- {
- if (glyphChar.GlyphType == GlyphType.String)
- stringCount++;
- }
- if (charCount > 0)
- {
- toUnicode.Append(charCount).AppendLine(" beginbfchar");
- foreach (GlyphChar glyphChar in pdfFont.UsedGlyphChars)
- {
- if (glyphChar.GlyphType == GlyphType.Character)
- {
- toUnicode.Append("<").Append(glyphChar.Glyph.ToString("X4")).Append("> ");
- toUnicode.Append("<").Append(((ushort)glyphChar.Character).ToString("X4")).AppendLine(">");
- }
- else if (glyphChar.GlyphType == GlyphType.None)
- {
- toUnicode.Append("<").Append(glyphChar.Glyph.ToString("X4")).Append("> ");
- toUnicode.AppendLine("<0000>");
- }
- }
- toUnicode.AppendLine("endbfchar");
- }
- if (stringCount > 0)
- {
- toUnicode.Append(stringCount.ToString()).AppendLine(" beginbfrange");
- foreach (GlyphChar glyphChar in pdfFont.UsedGlyphChars)
- {
- if (glyphChar.GlyphType == GlyphType.String)
- {
- toUnicode.Append("<").Append(glyphChar.Glyph.ToString("X4")).Append("> ");
- toUnicode.Append("<").Append(glyphChar.Glyph.ToString("X4")).Append("> ");
- toUnicode.Append("[<");
- foreach (char c in glyphChar.String)
- toUnicode.Append(((ushort)c).ToString("X4"));
- toUnicode.AppendLine(">]");
- }
- }
- toUnicode.AppendLine("endbfrange");
- }
- toUnicode.AppendLine("endcmap");
- toUnicode.AppendLine("CMapName currentdict /CMap defineresource pop");
- toUnicode.AppendLine("end");
- toUnicode.AppendLine("end");
- return toUnicode.ToString();
- }
- private void WriteFont(ExportTTFFont pdfFont)
- {
- long fontFileId = 0;
- #if USE_POSTSCRIPT_NAME
- string fontName = pdfFont.PostscriptName;
- #else
- string fontName = pdfFont.GetEnglishFontName();
- #endif
- // embedded font
- if (embeddingFonts)
- {
- if (interactiveForms && pdfFont.Editable)
- {
- if (interactiveFormsFontSetPattern.Length == 0)
- {
- List<Task> tasks = new List<Task>();
- for (int i = 0; i < 1024; i++)
- {
- int index = i;
- tasks.Add(Task.Run(() =>
- {
- StringBuilder sb = new StringBuilder(64);
- for (int j = 0; j < 64; j++)
- sb.Append((char)(64 * index + j));
- foreach (ExportTTFFont.RunInfo run in pdfFont.GetFontRuns(sb.ToString(), false))
- pdfFont.AddUsedGlyphs(run);
- }));
- }
- Task.WaitAll(tasks.ToArray());
- }
- else
- {
- foreach (ExportTTFFont.RunInfo run in pdfFont.GetPatternRuns(interactiveFormsFontSetPattern, false))
- pdfFont.AddUsedGlyphs(run);
- }
- }
- byte[] fontfile = pdfFont.GetFontData(true);
- if (fontfile != null)
- {
- skipCurrentFont = false;
- fontFileId = UpdateXRef();
- WriteLn(pdf, ObjNumber(fontFileId));
- MemoryStream fontFileStream = new MemoryStream();
- fontFileStream.Write(fontfile, 0, fontfile.Length);
- fontFileStream.Seek(0, SeekOrigin.Begin);
- WritePDFStream(pdf, fontFileStream, fontFileId, compressed, encrypted, true, true);
- }
- else
- {
- // If font cannot be embedded by some reason, for example license rights, then disable embedding
- skipCurrentFont = true;
- }
- }
- // descriptor
- long descriptorId = UpdateXRef();
- WriteLn(pdf, ObjNumber(descriptorId));
- WriteLn(pdf, "<<");
- WriteLn(pdf, "/Type /FontDescriptor");
- WriteLn(pdf, "/FontName /" + fontName);
- //WriteLn(pdf, "/FontFamily /" + fontName);
- WriteLn(pdf, "/Flags 32");
- WriteLn(pdf, "/FontBBox [" + pdfFont.TextMetric.otmrcFontBox.left.ToString() + " " +
- pdfFont.TextMetric.otmrcFontBox.bottom.ToString() + " " +
- pdfFont.TextMetric.otmrcFontBox.right.ToString() + " " +
- pdfFont.TextMetric.otmrcFontBox.top.ToString() + " ]");
- //WriteLn(pdf, "/Style << /Panose <" + pdfFont.GetPANOSE() + "> >>");
- int ItalicAnggle = pdfFont.TextMetric.otmItalicAngle;
- if (pdfFont.NeedSimulateItalic && ItalicAnggle == 0)
- WriteLn(pdf, "/ItalicAngle " + 16);
- else
- WriteLn(pdf, "/ItalicAngle " + pdfFont.TextMetric.otmItalicAngle.ToString());
- #if !WITHOUT_UNISCRIBE
- WriteLn(pdf, "/Ascent " + pdfFont.TextMetric.otmAscent.ToString());
- WriteLn(pdf, "/Descent " + pdfFont.TextMetric.otmDescent.ToString());
- WriteLn(pdf, "/CapHeight " + pdfFont.TextMetric.otmTextMetrics.tmHeight.ToString());
- #else
- WriteLn(pdf, "/Ascent " + ((int)(pdfFont.TextMetric.otmAscent / 2.05)).ToString());
- WriteLn(pdf, "/Descent " + ((int)(pdfFont.TextMetric.otmDescent / 2.05)).ToString());
- WriteLn(pdf, "/CapHeight " + ((int)(pdfFont.TextMetric.otmTextMetrics.tmHeight / 2.05)).ToString());
- #endif
- WriteLn(pdf, "/Leading " + pdfFont.TextMetric.otmTextMetrics.tmInternalLeading.ToString());
- WriteLn(pdf, "/StemV " + (50 + Math.Round(Math.Sqrt((float)pdfFont.TextMetric.otmTextMetrics.tmWeight / 65f))).ToString());
- WriteLn(pdf, "/AvgWidth " + pdfFont.TextMetric.otmTextMetrics.tmAveCharWidth.ToString());
- WriteLn(pdf, "/MxWidth " + pdfFont.TextMetric.otmTextMetrics.tmMaxCharWidth.ToString());
- WriteLn(pdf, "/MissingWidth " + pdfFont.TextMetric.otmTextMetrics.tmAveCharWidth.ToString());
- if (embeddingFonts && !skipCurrentFont)
- WriteLn(pdf, "/FontFile2 " + ObjNumberRef(fontFileId));
- WriteLn(pdf, ">>");
- WriteLn(pdf, "endobj");
- // ToUnicode
- long toUnicodeId = UpdateXRef();
- WriteLn(pdf, ObjNumber(toUnicodeId));
- MemoryStream tounicodeStream = new MemoryStream();
- Write(tounicodeStream, GetToUnicode(pdfFont));
- tounicodeStream.Position = 0;
- WritePDFStream(pdf, tounicodeStream, toUnicodeId, compressed, encrypted, true, true);
- //CIDSystemInfo
- long cIDSystemInfoId = UpdateXRef();
- WriteLn(pdf, ObjNumber(cIDSystemInfoId));
- WriteLn(pdf, "<<");
- WriteLn(pdf, "/Registry (Adobe) /Ordering (Identity) /Supplement 0");
- WriteLn(pdf, ">>");
- WriteLn(pdf, "endobj");
- //DescendantFonts
- long descendantFontId = UpdateXRef();
- WriteLn(pdf, ObjNumber(descendantFontId));
- WriteLn(pdf, "<<");
- WriteLn(pdf, "/Type /Font");
- WriteLn(pdf, "/Subtype /CIDFontType2");
- WriteLn(pdf, "/BaseFont /" + fontName);
- WriteLn(pdf, "/CIDToGIDMap /Identity");
- WriteLn(pdf, "/CIDSystemInfo " + ObjNumberRef(cIDSystemInfoId));
- WriteLn(pdf, "/FontDescriptor " + ObjNumberRef(descriptorId));
- Write(pdf, "/W [ ");
- foreach (GlyphChar glyphChar in pdfFont.UsedGlyphChars)
- Write(pdf, glyphChar.Glyph.ToString() + " [" + FloatToString(glyphChar.Width) + "] ");
- WriteLn(pdf, "]");
- WriteLn(pdf, ">>");
- WriteLn(pdf, "endobj");
- // main
- xRef[(int)(pdfFont.Reference - 1)] = pdf.Position;
- WriteLn(pdf, ObjNumber(pdfFont.Reference));
- WriteLn(pdf, "<<");
- WriteLn(pdf, "/Type /Font");
- WriteLn(pdf, "/Subtype /Type0");
- WriteLn(pdf, "/BaseFont /" + fontName);
- WriteLn(pdf, "/Encoding /Identity-H");
- WriteLn(pdf, "/DescendantFonts [" + ObjNumberRef(descendantFontId) + "]");
- WriteLn(pdf, "/ToUnicode " + ObjNumberRef(toUnicodeId));
- WriteLn(pdf, ">>");
- WriteLn(pdf, "endobj");
- }
- }
- }
|