internal PdfType0Font(TrueTypeFont ttf, String cmap) : base() { if (!cmap.Equals(PdfEncodings.IDENTITY_H) && !cmap.Equals(PdfEncodings.IDENTITY_V)) { throw new PdfException("only.identity.cmaps.supports.with.truetype"); } if (!ttf.GetFontNames().AllowEmbedding()) { throw new PdfException("1.cannot.be.embedded.due.to.licensing.restrictions").SetMessageParams(ttf.GetFontNames ().GetFontName() + ttf.GetFontNames().GetStyle()); } this.fontProgram = ttf; this.embedded = true; vertical = cmap.EndsWith("V"); cmapEncoding = new CMapEncoding(cmap); longTag = new LinkedDictionary <int, int[]>(); cidFontType = CID_FONT_TYPE_2; if (ttf.IsFontSpecific()) { specificUnicodeDifferences = new char[256]; byte[] bytes = new byte[1]; for (int k = 0; k < 256; ++k) { bytes[0] = (byte)k; String s = PdfEncodings.ConvertToString(bytes, null); char ch = s.Length > 0 ? s[0] : '?'; specificUnicodeDifferences[k] = ch; } } }
internal PdfType0Font(TrueTypeFont ttf, String cmap) : base() { if (!PdfEncodings.IDENTITY_H.Equals(cmap) && !PdfEncodings.IDENTITY_V.Equals(cmap)) { throw new PdfException(PdfException.OnlyIdentityCMapsSupportsWithTrueType); } if (!ttf.GetFontNames().AllowEmbedding()) { throw new PdfException(PdfException.CannotBeEmbeddedDueToLicensingRestrictions).SetMessageParams(ttf.GetFontNames ().GetFontName() + ttf.GetFontNames().GetStyle()); } this.fontProgram = ttf; this.embedded = true; vertical = cmap.EndsWith("V"); cmapEncoding = new CMapEncoding(cmap); longTag = new SortedSet <int>(); cidFontType = CID_FONT_TYPE_2; if (ttf.IsFontSpecific()) { specificUnicodeDifferences = new char[256]; byte[] bytes = new byte[1]; for (int k = 0; k < 256; ++k) { bytes[0] = (byte)k; String s = PdfEncodings.ConvertToString(bytes, null); char ch = s.Length > 0 ? s[0] : '?'; specificUnicodeDifferences[k] = ch; } } }
private void FlushFontData() { if (cidFontType == CID_FONT_TYPE_0) { GetPdfObject().Put(PdfName.Type, PdfName.Font); GetPdfObject().Put(PdfName.Subtype, PdfName.Type0); String name = fontProgram.GetFontNames().GetFontName(); String style = fontProgram.GetFontNames().GetStyle(); if (style.Length > 0) { name += "-" + style; } GetPdfObject().Put(PdfName.BaseFont, new PdfName(String.Format("{0}-{1}", name, cmapEncoding.GetCmapName() ))); GetPdfObject().Put(PdfName.Encoding, new PdfName(cmapEncoding.GetCmapName())); PdfDictionary fontDescriptor = GetFontDescriptor(name); int[][] metrics = longTag.Values.ToArray(new int[0][]); iText.IO.Util.JavaUtil.Sort(metrics, new PdfType0Font.MetricComparator()); PdfDictionary cidFont = GetCidFontType2(null, fontDescriptor, fontProgram.GetFontNames().GetFontName(), metrics ); GetPdfObject().Put(PdfName.DescendantFonts, new PdfArray(cidFont)); fontDescriptor.Flush(); cidFont.Flush(); } else { if (cidFontType == CID_FONT_TYPE_2) { TrueTypeFont ttf = (TrueTypeFont)GetFontProgram(); AddRangeUni(ttf, longTag, true); int[][] metrics = longTag.Values.ToArray(new int[0][]); iText.IO.Util.JavaUtil.Sort(metrics, new PdfType0Font.MetricComparator()); PdfStream fontStream; String fontName = ttf.GetFontNames().GetFontName(); if (subset) { fontName = CreateSubsetPrefix() + fontName; } PdfDictionary fontDescriptor = GetFontDescriptor(fontName); if (ttf.IsCff()) { byte[] cffBytes = ttf.GetFontStreamBytes(); if (subset || subsetRanges != null) { CFFFontSubset cff = new CFFFontSubset(ttf.GetFontStreamBytes(), longTag); cffBytes = cff.Process(cff.GetNames()[0]); } fontStream = GetPdfFontStream(cffBytes, new int[] { cffBytes.Length }); fontStream.Put(PdfName.Subtype, new PdfName("CIDFontType0C")); // The PDF Reference manual advises to add -cmap in case CIDFontType0 GetPdfObject().Put(PdfName.BaseFont, new PdfName(String.Format("{0}-{1}", fontName, cmapEncoding.GetCmapName ()))); fontDescriptor.Put(PdfName.FontFile3, fontStream); } else { byte[] ttfBytes; if (subset || ttf.GetDirectoryOffset() != 0) { ttfBytes = ttf.GetSubset(new LinkedHashSet <int>(longTag.Keys), true); } else { ttfBytes = ttf.GetFontStreamBytes(); } fontStream = GetPdfFontStream(ttfBytes, new int[] { ttfBytes.Length }); GetPdfObject().Put(PdfName.BaseFont, new PdfName(fontName)); fontDescriptor.Put(PdfName.FontFile2, fontStream); } // CIDSet shall be based on font.maxGlyphId property of the font, it is maxp.numGlyphs for ttf, // because technically we convert all unused glyphs to space, e.g. just remove outlines. int maxGlyphId = ttf.GetFontMetrics().GetMaxGlyphId(); byte[] cidSetBytes = new byte[ttf.GetFontMetrics().GetMaxGlyphId() / 8 + 1]; for (int i = 0; i < maxGlyphId / 8; i++) { cidSetBytes[i] |= 0xff; } for (int i_1 = 0; i_1 < maxGlyphId % 8; i_1++) { cidSetBytes[cidSetBytes.Length - 1] |= rotbits[i_1]; } fontDescriptor.Put(PdfName.CIDSet, new PdfStream(cidSetBytes)); PdfDictionary cidFont = GetCidFontType2(ttf, fontDescriptor, fontName, metrics); GetPdfObject().Put(PdfName.Type, PdfName.Font); GetPdfObject().Put(PdfName.Subtype, PdfName.Type0); GetPdfObject().Put(PdfName.Encoding, new PdfName(cmapEncoding.GetCmapName())); GetPdfObject().Put(PdfName.DescendantFonts, new PdfArray(cidFont)); PdfStream toUnicode = GetToUnicode(metrics); if (toUnicode != null) { GetPdfObject().Put(PdfName.ToUnicode, toUnicode); toUnicode.Flush(); } fontDescriptor.Flush(); cidFont.Flush(); } else { throw new InvalidOperationException("Unsupported CID Font"); } } }
private void FlushFontData() { if (cidFontType == CID_FONT_TYPE_0) { GetPdfObject().Put(PdfName.Type, PdfName.Font); GetPdfObject().Put(PdfName.Subtype, PdfName.Type0); String name = fontProgram.GetFontNames().GetFontName(); String style = fontProgram.GetFontNames().GetStyle(); if (style.Length > 0) { name += "-" + style; } GetPdfObject().Put(PdfName.BaseFont, new PdfName(MessageFormatUtil.Format("{0}-{1}", name, cmapEncoding.GetCmapName ()))); GetPdfObject().Put(PdfName.Encoding, new PdfName(cmapEncoding.GetCmapName())); PdfDictionary fontDescriptor = GetFontDescriptor(name); PdfDictionary cidFont = GetCidFont(fontDescriptor, fontProgram.GetFontNames().GetFontName(), false); GetPdfObject().Put(PdfName.DescendantFonts, new PdfArray(cidFont)); fontDescriptor.Flush(); cidFont.Flush(); } else { if (cidFontType == CID_FONT_TYPE_2) { TrueTypeFont ttf = (TrueTypeFont)GetFontProgram(); String fontName = UpdateSubsetPrefix(ttf.GetFontNames().GetFontName(), subset, embedded); PdfDictionary fontDescriptor = GetFontDescriptor(fontName); PdfStream fontStream; ttf.UpdateUsedGlyphs((SortedSet <int>)longTag, subset, subsetRanges); if (ttf.IsCff()) { byte[] cffBytes; if (subset) { cffBytes = new CFFFontSubset(ttf.GetFontStreamBytes(), longTag).Process(); } else { cffBytes = ttf.GetFontStreamBytes(); } fontStream = GetPdfFontStream(cffBytes, new int[] { cffBytes.Length }); fontStream.Put(PdfName.Subtype, new PdfName("CIDFontType0C")); // The PDF Reference manual advises to add -cmap in case CIDFontType0 GetPdfObject().Put(PdfName.BaseFont, new PdfName(MessageFormatUtil.Format("{0}-{1}", fontName, cmapEncoding .GetCmapName()))); fontDescriptor.Put(PdfName.FontFile3, fontStream); } else { byte[] ttfBytes = null; //getDirectoryOffset() > 0 means ttc, which shall be subsetted anyway. if (subset || ttf.GetDirectoryOffset() > 0) { try { ttfBytes = ttf.GetSubset(longTag, subset); } catch (iText.IO.IOException) { ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Font.PdfType0Font)); logger.Warn(iText.IO.LogMessageConstant.FONT_SUBSET_ISSUE); ttfBytes = null; } } if (ttfBytes == null) { ttfBytes = ttf.GetFontStreamBytes(); } fontStream = GetPdfFontStream(ttfBytes, new int[] { ttfBytes.Length }); GetPdfObject().Put(PdfName.BaseFont, new PdfName(fontName)); fontDescriptor.Put(PdfName.FontFile2, fontStream); } // CIDSet shall be based on font.numberOfGlyphs property of the font, it is maxp.numGlyphs for ttf, // because technically we convert all unused glyphs to space, e.g. just remove outlines. int numOfGlyphs = ttf.GetFontMetrics().GetNumberOfGlyphs(); byte[] cidSetBytes = new byte[ttf.GetFontMetrics().GetNumberOfGlyphs() / 8 + 1]; for (int i = 0; i < numOfGlyphs / 8; i++) { cidSetBytes[i] |= 0xff; } for (int i = 0; i < numOfGlyphs % 8; i++) { cidSetBytes[cidSetBytes.Length - 1] |= rotbits[i]; } fontDescriptor.Put(PdfName.CIDSet, new PdfStream(cidSetBytes)); PdfDictionary cidFont = GetCidFont(fontDescriptor, fontName, !ttf.IsCff()); GetPdfObject().Put(PdfName.Type, PdfName.Font); GetPdfObject().Put(PdfName.Subtype, PdfName.Type0); GetPdfObject().Put(PdfName.Encoding, new PdfName(cmapEncoding.GetCmapName())); GetPdfObject().Put(PdfName.DescendantFonts, new PdfArray(cidFont)); PdfStream toUnicode = GetToUnicode(); if (toUnicode != null) { GetPdfObject().Put(PdfName.ToUnicode, toUnicode); if (toUnicode.GetIndirectReference() != null) { toUnicode.Flush(); } } // getPdfObject().getIndirectReference() != null by assertion of PdfType0Font#flush() // This means, that fontDescriptor, cidFont and fontStream already are indirects if (GetPdfObject().GetIndirectReference().GetDocument().GetPdfVersion().CompareTo(PdfVersion.PDF_2_0) >= 0 ) { // CIDSet is deprecated in PDF 2.0 fontDescriptor.Remove(PdfName.CIDSet); } fontDescriptor.Flush(); cidFont.Flush(); fontStream.Flush(); } else { throw new InvalidOperationException("Unsupported CID Font"); } } }