/// <summary>Generates the CIDFontTyte2 dictionary.</summary> /// <param name="fontDescriptor">the indirect reference to the font descriptor</param> /// <param name="fontName">a name of the font</param> /// <param name="metrics">the horizontal width metrics</param> /// <returns>fully initialized CIDFont</returns> protected internal virtual PdfDictionary GetCidFontType2(TrueTypeFont ttf, PdfDictionary fontDescriptor, String fontName, int[][] metrics) { PdfDictionary cidFont = new PdfDictionary(); MarkObjectAsIndirect(cidFont); cidFont.Put(PdfName.Type, PdfName.Font); // sivan; cff cidFont.Put(PdfName.FontDescriptor, fontDescriptor); if (ttf == null || ttf.IsCff()) { cidFont.Put(PdfName.Subtype, PdfName.CIDFontType0); } else { cidFont.Put(PdfName.Subtype, PdfName.CIDFontType2); cidFont.Put(PdfName.CIDToGIDMap, PdfName.Identity); } cidFont.Put(PdfName.BaseFont, new PdfName(fontName)); PdfDictionary cidInfo = new PdfDictionary(); cidInfo.Put(PdfName.Registry, new PdfString(cmapEncoding.GetRegistry())); cidInfo.Put(PdfName.Ordering, new PdfString(cmapEncoding.GetOrdering())); cidInfo.Put(PdfName.Supplement, new PdfNumber(cmapEncoding.GetSupplement())); cidFont.Put(PdfName.CIDSystemInfo, cidInfo); if (!vertical) { cidFont.Put(PdfName.DW, new PdfNumber(FontProgram.DEFAULT_WIDTH)); StringBuilder buf = new StringBuilder("["); int lastNumber = -10; bool firstTime = true; foreach (int[] metric in metrics) { Glyph glyph = fontProgram.GetGlyphByCode(metric[0]); if (glyph.GetWidth() == FontProgram.DEFAULT_WIDTH) { continue; } if (glyph.GetCode() == lastNumber + 1) { buf.Append(' ').Append(glyph.GetWidth()); } else { if (!firstTime) { buf.Append(']'); } firstTime = false; buf.Append(glyph.GetCode()).Append('[').Append(glyph.GetWidth()); } lastNumber = glyph.GetCode(); } if (buf.Length > 1) { buf.Append("]]"); cidFont.Put(PdfName.W, new PdfLiteral(buf.ToString())); } } else { throw new NotSupportedException("Vertical writing has not implemented yet."); } return(cidFont); }
protected internal virtual PdfDictionary GetCidFontType2(TrueTypeFont ttf, PdfDictionary fontDescriptor, String fontName, int[] glyphIds) { return(GetCidFont(fontDescriptor, fontName, ttf != null && !ttf.IsCff())); }
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"); } } }