public virtual void AddUnusedStreamObjectsTest() { String outPdf = destinationFolder + "pdfA1b_docWithUnusedObjects_3.pdf"; String cmpPdf = sourceFolder + "cmp/PdfAFlushingTest/cmp_pdfA1b_docWithUnusedObjects_3.pdf"; PdfWriter writer = new PdfWriter(outPdf); Stream @is = new FileStream(sourceFolder + "sRGB Color Space Profile.icm", FileMode.Open, FileAccess.Read); PdfADocument pdfDocument = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_1B, new PdfOutputIntent("Custom" , "", "http://www.color.org", "sRGB IEC61966-2.1", @is)); pdfDocument.AddNewPage(); PdfDictionary unusedDictionary = new PdfDictionary(); PdfArray unusedArray = (PdfArray) new PdfArray().MakeIndirect(pdfDocument); unusedArray.Add(new PdfNumber(42)); PdfStream stream = new PdfStream(new byte[] { 1, 2, 34, 45 }, 0); unusedArray.Add(stream); unusedDictionary.Put(new PdfName("testName"), unusedArray); unusedDictionary.MakeIndirect(pdfDocument).Flush(); unusedDictionary.Flush(); pdfDocument.Close(); PdfReader testerReader = new PdfReader(outPdf); PdfDocument testerDocument = new PdfDocument(testerReader); NUnit.Framework.Assert.AreEqual(testerDocument.ListIndirectReferences().Count, 11); testerDocument.Close(); CompareResult(outPdf, cmpPdf); }
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"); } } }
protected internal virtual void FlushFontData(String fontName, PdfName subtype) { GetPdfObject().Put(PdfName.Subtype, subtype); if (fontName != null && fontName.Length > 0) { GetPdfObject().Put(PdfName.BaseFont, new PdfName(fontName)); } int firstChar; int lastChar; for (firstChar = 0; firstChar < 256; ++firstChar) { if (shortTag[firstChar] != 0) { break; } } for (lastChar = 255; lastChar >= firstChar; --lastChar) { if (shortTag[lastChar] != 0) { break; } } if (firstChar > 255) { firstChar = 255; lastChar = 255; } if (!IsSubset() || !IsEmbedded()) { firstChar = 0; lastChar = shortTag.Length - 1; for (int k = 0; k < shortTag.Length; ++k) { // remove unsupported by encoding values in case custom encoding. // save widths information in case standard pdf encodings (winansi or macroman) if (fontEncoding.CanDecode(k)) { shortTag[k] = 1; } else { if (!fontEncoding.HasDifferences() && fontProgram.GetGlyphByCode(k) != null) { shortTag[k] = 1; } else { shortTag[k] = 0; } } } } if (fontEncoding.HasDifferences()) { // trim range of symbols for (int k = firstChar; k <= lastChar; ++k) { if (!FontEncoding.NOTDEF.Equals(fontEncoding.GetDifference(k))) { firstChar = k; break; } } for (int k = lastChar; k >= firstChar; --k) { if (!FontEncoding.NOTDEF.Equals(fontEncoding.GetDifference(k))) { lastChar = k; break; } } PdfDictionary enc = new PdfDictionary(); enc.Put(PdfName.Type, PdfName.Encoding); PdfArray diff = new PdfArray(); bool gap = true; for (int k = firstChar; k <= lastChar; ++k) { if (shortTag[k] != 0) { if (gap) { diff.Add(new PdfNumber(k)); gap = false; } diff.Add(new PdfName(fontEncoding.GetDifference(k))); } else { gap = true; } } enc.Put(PdfName.Differences, diff); GetPdfObject().Put(PdfName.Encoding, enc); } else { if (!fontEncoding.IsFontSpecific()) { GetPdfObject().Put(PdfName.Encoding, PdfEncodings.CP1252.Equals(fontEncoding.GetBaseEncoding()) ? PdfName. WinAnsiEncoding : PdfName.MacRomanEncoding); } } if (IsForceWidthsOutput() || !IsBuiltInFont() || fontEncoding.HasDifferences()) { GetPdfObject().Put(PdfName.FirstChar, new PdfNumber(firstChar)); GetPdfObject().Put(PdfName.LastChar, new PdfNumber(lastChar)); PdfArray wd = new PdfArray(); for (int k = firstChar; k <= lastChar; ++k) { if (shortTag[k] == 0) { wd.Add(new PdfNumber(0)); } else { //prevent lost of widths info int uni = fontEncoding.GetUnicode(k); Glyph glyph = uni > -1 ? GetGlyph(uni) : fontProgram.GetGlyphByCode(k); wd.Add(new PdfNumber(glyph != null ? glyph.GetWidth() : 0)); } } GetPdfObject().Put(PdfName.Widths, wd); } PdfDictionary fontDescriptor = !IsBuiltInFont() ? GetFontDescriptor(fontName) : null; if (fontDescriptor != null) { GetPdfObject().Put(PdfName.FontDescriptor, fontDescriptor); if (fontDescriptor.GetIndirectReference() != null) { fontDescriptor.Flush(); } } }
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"); } } }