Пример #1
0
        internal PdfType0Font(Document document, TrueTypeFont ttf, bool embedSubset, bool closeTTF, bool vertical)
            : base(document, new PdfDictionary())
        {
            if (vertical)
            {
                ttf.EnableVerticalSubstitutions();
            }

            gsubData   = ttf.GsubData;
            cmapLookup = ttf.GetUnicodeCmapLookup();

            embedder = new PdfCIDFontType2Embedder(document, Dictionary, ttf, embedSubset, this, vertical);
            CIDFont  = embedder.GetCIDFont();
            ReadEncoding();
            if (closeTTF)
            {
                if (embedSubset)
                {
                    this.ttf = ttf;
                    //TODO document.registerTrueTypeFontForClosing(ttf);
                }
                else
                {
                    // the TTF is fully loaded and it is safe to close the underlying data source
                    ttf.Dispose();
                }
            }
        }
        /**
         * Creates a new TrueType font embedder for the given TTF as a PDCIDFontType2.
         *
         * @param document parent document
         * @param dict font dictionary
         * @param ttf True Type Font
         * @param parent parent Type 0 font
         * @ if the TTF could not be read
         */
        public PdfCIDFontType2Embedder(Document document, PdfDictionary dict, TrueTypeFont ttf, bool embedSubset, PdfType0Font parent, bool vertical)
            : base(document, dict, ttf, embedSubset)
        {
            this.document = document;
            this.dict     = dict;
            this.parent   = parent;
            this.vertical = vertical;

            // parent Type 0 font
            dict[PdfName.Subtype]  = PdfName.Type0;
            dict[PdfName.BaseFont] = PdfName.Get(FontDescriptor.FontName);
            dict[PdfName.Encoding] = vertical ? PdfName.IdentityV : PdfName.IdentityH; // CID = GID

            // descendant CIDFont
            cidFont = CreateCIDFont();
            PdfArray descendantFonts = new PdfArray();

            descendantFonts.Add(document.File.Register(cidFont));
            dict[PdfName.DescendantFonts] = descendantFonts;

            if (!embedSubset)
            {
                // build GID -> Unicode map
                BuildToUnicodeCMap(null);
            }
        }
Пример #3
0
        /**
         * Creates a new TrueType font for embedding.
         */
        public TrueTypeEmbedder(Document document, PdfDictionary dict, TrueTypeFont ttf, bool embedSubset)
        {
            this.document    = document;
            this.embedSubset = embedSubset;
            this.ttf         = ttf;
            fontDescriptor   = CreateFontDescriptor(ttf);

            if (!IsEmbeddingPermitted(ttf))
            {
                throw new IOException("This font does not permit embedding");
            }

            if (!embedSubset)
            {
                // full embedding
                PdfStream stream = new PdfStream(ttf.OriginalData);
                stream.Header[PdfName.Length]      =
                    stream.Header[PdfName.Length1] = PdfInteger.Get(ttf.OriginalDataSize);
                fontDescriptor.FontFile2           = new FontFile(document, stream);
            }
            dict[PdfName.Type]     = PdfName.Font;
            dict[PdfName.BaseFont] = new PdfName(ttf.Name);

            // choose a Unicode "cmap"
            cmapLookup = ttf.GetUnicodeCmapLookup();
        }
Пример #4
0
        /**
         * Constructor.
         *
         * @param fontDictionary The font dictionary according to the PDF specification.
         * @param parent The parent font.
         * @param trueTypeFont The true type font used to create the parent font
         * @throws IOException
         */
        public CIDFontType2(PdfDirectObject fontDictionary, PdfType0Font parent, TrueTypeFont trueTypeFont)
            : base(fontDictionary, parent)
        {
            FontDescriptor fd = FontDescriptor;

            if (trueTypeFont != null)
            {
                ttf        = trueTypeFont;
                isEmbedded = true;
                isDamaged  = false;
            }
            else
            {
                bool         fontIsDamaged = false;
                TrueTypeFont ttfFont       = null;

                FontFile stream = null;
                if (fd != null)
                {
                    // Acrobat looks in FontFile too, even though it is not in the spec, see PDFBOX-2599
                    stream = fd.FontFile2 ?? fd.FontFile3 ?? fd.FontFile;
                }
                if (stream != null)
                {
                    try
                    {
                        // embedded OTF or TTF
                        OTFParser otfParser = new OTFParser(true);
                        ttfFont = otfParser.Parse((Bytes.Buffer)stream.BaseDataObject.ExtractBody(true), fd.FontName);

                        if (ttfFont is OpenTypeFont otf && otf.IsPostScript)
                        {
                            // PDFBOX-3344 contains PostScript outlines instead of TrueType
                            fontIsDamaged = true;
                            Debug.WriteLine($"warning: Found CFF/OTF but expected embedded TTF font {fd.FontName}");
                        }
                    }
                    catch (IOException e)
                    {
                        fontIsDamaged = true;
                        Debug.WriteLine($"warning: Could not read embedded OTF for font {BaseFont} {e}");
                    }
                }
                isEmbedded = ttfFont != null;
                isDamaged  = fontIsDamaged;

                if (ttfFont == null)
                {
                    ttfFont = FindFontOrSubstitute();
                }
                ttf = ttfFont;
            }
            cmapLookup = ttf.GetUnicodeCmapLookup(false);
            cid2gid    = ReadCIDToGIDMap();
        }
Пример #5
0
        /**
         * Returns true if the fsType in the OS/2 table permits subsetting.
         */
        private bool IsSubsettingPermitted(TrueTypeFont ttf)
        {
            if (ttf.OS2Windows != null)

            {
                int fsType = ttf.OS2Windows.FsType;
                if ((fsType & OS2WindowsMetricsTable.FSTYPE_NO_SUBSETTING) ==
                    OS2WindowsMetricsTable.FSTYPE_NO_SUBSETTING)
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #6
0
        /**
         * Creates a new TrueType font for embedding.
         */
        private PdfTrueTypeFont(Document document, TrueTypeFont ttf, Encoding encoding, bool closeTTF)
            : base(document)
        {
            PDTrueTypeFontEmbedder embedder = new PDTrueTypeFontEmbedder(document, Dictionary, ttf, encoding);

            this.encoding  = encoding;
            this.ttf       = ttf;
            FontDescriptor = embedder.FontDescriptor;
            isEmbedded     = true;
            isDamaged      = false;
            glyphList      = GlyphMapping.Default;
            if (closeTTF)
            {
                // the TTF is fully loaded and it is safe to close the underlying data source
                ttf.Dispose();
            }
        }
        /**
         * Creates a new TrueType font embedder for the given TTF as a PDTrueTypeFont.
         *
         * @param document The parent document
         * @param dict Font dictionary
         * @param ttfStream TTF stream
         * @param encoding The PostScript encoding vector to be used for embedding.
         * @throws IOException if the TTF could not be read
         */
        public PDTrueTypeFontEmbedder(Document document, PdfDictionary dict, TrueTypeFont ttf, Encoding encoding)
            : base(document, dict, ttf, false)
        {
            dict[PdfName.Subtype] = PdfName.TrueType;

            var glyphList = GlyphMapping.Default;

            this.fontEncoding      = encoding;
            dict[PdfName.Encoding] = encoding.GetPdfObject();
            fontDescriptor.Flags  &= ~FlagsEnum.Symbolic;
            fontDescriptor.Flags  |= FlagsEnum.Nonsymbolic;

            // add the font descriptor
            dict[PdfName.FontDescriptor] = fontDescriptor.BaseObject;

            // set the glyph widths
            SetWidths(dict, glyphList);
        }
Пример #8
0
        internal PdfTrueTypeFont(PdfDirectObject baseObject)
            : base(baseObject)
        {
            TrueTypeFont ttfFont       = null;
            bool         fontIsDamaged = false;

            if (FontDescriptor != null)
            {
                var fd        = base.FontDescriptor;
                var ff2Stream = fd.FontFile2;
                if (ff2Stream != null)
                {
                    try
                    {
                        // embedded
                        TTFParser ttfParser = new TTFParser(true);
                        ttfFont = ttfParser.Parse(ff2Stream.BaseDataObject.ExtractBody(true));
                    }
                    catch (IOException e)
                    {
                        Debug.WriteLine($"warn: Could not read embedded TTF for font {BaseFont} {e}");
                        fontIsDamaged = true;
                    }
                }
            }
            isEmbedded = ttfFont != null;
            isDamaged  = fontIsDamaged;

            // substitute
            if (ttfFont == null)
            {
                FontMapping <TrueTypeFont> mapping = FontMappers.Instance.GetTrueTypeFont(BaseFont, FontDescriptor);
                ttfFont = mapping.Font;

                if (mapping.IsFallback)
                {
                    Debug.WriteLine($"warn: Using fallback font '{ttfFont}' for '{BaseFont}'");
                }
            }
            ttf = ttfFont;
            ReadEncoding();
        }
Пример #9
0
        public void BuildFontFile2(Bytes.Buffer ttfStream)
        {
            PdfStream stream = new PdfStream(ttfStream);

            // as the stream was closed within the PdfStream constructor, we have to recreate it
            using (var input = (Bytes.Buffer)stream.ExtractBody(true))
            {
                ttf = new TTFParser().ParseEmbedded(input);
                if (!IsEmbeddingPermitted(ttf))
                {
                    throw new IOException("This font does not permit embedding");
                }
                if (fontDescriptor == null)
                {
                    fontDescriptor = CreateFontDescriptor(ttf);
                }
            }
            stream.Header[PdfName.Length1] = PdfInteger.Get(ttf.OriginalDataSize);
            fontDescriptor.FontFile2       = new FontFile(document, stream);
        }
Пример #10
0
 /**
  * Returns true if the fsType in the OS/2 table permits embedding.
  */
 private bool IsEmbeddingPermitted(TrueTypeFont ttf)
 {
     if (ttf.OS2Windows != null)
     {
         int fsType = ttf.OS2Windows.FsType;
         if ((fsType & OS2WindowsMetricsTable.FSTYPE_RESTRICTED) ==
             OS2WindowsMetricsTable.FSTYPE_RESTRICTED)
         {
             // restricted License embedding
             return(false);
         }
         else if ((fsType & OS2WindowsMetricsTable.FSTYPE_BITMAP_ONLY) ==
                  OS2WindowsMetricsTable.FSTYPE_BITMAP_ONLY)
         {
             // bitmap embedding only
             return(false);
         }
     }
     return(true);
 }
Пример #11
0
        public FontMapperImpl()
        {
            // substitutes for standard 14 fonts
            substitutes.Add("Courier", new List <string> {
                "CourierNew", "CourierNewPSMT", "LiberationMono", "NimbusMonL-Regu"
            });
            substitutes.Add("Courier-Bold", new List <string> {
                "CourierNewPS-BoldMT", "CourierNew-Bold", "LiberationMono-Bold", "NimbusMonL-Bold"
            });
            substitutes.Add("Courier-Oblique", new List <string> {
                "CourierNewPS-ItalicMT", "CourierNew-Italic", "LiberationMono-Italic", "NimbusMonL-ReguObli"
            });
            substitutes.Add("Courier-BoldOblique", new List <string> {
                "CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", "LiberationMono-BoldItalic", "NimbusMonL-BoldObli"
            });
            substitutes.Add("Helvetica", new List <string> {
                "ArialMT", "Arial", "LiberationSans", "NimbusSanL-Regu"
            });
            substitutes.Add("Helvetica-Bold", new List <string> {
                "Arial-BoldMT", "Arial-Bold", "LiberationSans-Bold", "NimbusSanL-Bold"
            });
            substitutes.Add("Helvetica-Oblique", new List <string> {
                "Arial-ItalicMT", "Arial-Italic", "Helvetica-Italic", "LiberationSans-Italic", "NimbusSanL-ReguItal"
            });
            substitutes.Add("Helvetica-BoldOblique", new List <string> {
                "Arial-BoldItalicMT", "Helvetica-BoldItalic", "LiberationSans-BoldItalic", "NimbusSanL-BoldItal"
            });
            substitutes.Add("Times-Roman", new List <string> {
                "TimesNewRomanPSMT", "TimesNewRoman", "TimesNewRomanPS", "LiberationSerif", "NimbusRomNo9L-Regu"
            });
            substitutes.Add("Times-Bold", new List <string> {
                "TimesNewRomanPS-BoldMT", "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", "LiberationSerif-Bold", "NimbusRomNo9L-Medi"
            });
            substitutes.Add("Times-Italic", new List <string> {
                "TimesNewRomanPS-ItalicMT", "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", "LiberationSerif-Italic", "NimbusRomNo9L-ReguItal"
            });
            substitutes.Add("Times-BoldItalic", new List <string> {
                "TimesNewRomanPS-BoldItalicMT", "TimesNewRomanPS-BoldItalic", "TimesNewRoman-BoldItalic", "LiberationSerif-BoldItalic", "NimbusRomNo9L-MediItal"
            });
            substitutes.Add("Symbol", new List <string> {
                "Symbol", "SymbolMT", "StandardSymL"
            });
            substitutes.Add("ZapfDingbats", new List <string> {
                "ZapfDingbatsITCbyBT-Regular", "ZapfDingbatsITC", "Dingbats", "MS-Gothic"
            });

            // Acrobat also uses alternative names for Standard 14 fonts, which we map to those above
            // these include names such as "Arial" and "TimesNewRoman"
            foreach (string baseName in Standard14Fonts.Names)
            {
                if (!substitutes.ContainsKey(baseName))
                {
                    string mappedName = Standard14Fonts.GetMappedFontName(baseName);
                    substitutes.Add(baseName, CopySubstitutes(mappedName));
                }
            }

            // -------------------------

            try
            {
                string ttfName   = "fonts.ttf.LiberationSans-Regular";
                var    ttfStream = typeof(IFontMapper).Assembly.GetManifestResourceStream(ttfName);
                if (ttfStream == null)
                {
                    throw new IOException("Error loading resource: " + ttfName);
                }
                TTFParser ttfParser = new TTFParser();
                lastResortFont = ttfParser.Parse(ttfStream);
            }
            catch (IOException e)
            {
                throw new Exception("Load LiberationSans", e);
            }
        }
Пример #12
0
        /**
         * Creates a new font descriptor dictionary for the given TTF.
         */
        private FontDescriptor CreateFontDescriptor(TrueTypeFont ttf)
        {
            FontDescriptor fd = new FontDescriptor(document, new PdfDictionary());

            fd.FontName = ttf.Name;

            OS2WindowsMetricsTable os2  = ttf.OS2Windows;
            PostScriptTable        post = ttf.PostScript;

            // Flags
            var flags = (FlagsEnum)0;

            flags |= (post.IsFixedPitch > 0 || ttf.HorizontalHeader.NumberOfHMetrics == 1) ? FlagsEnum.FixedPitch : 0;

            int fsSelection = os2.FsSelection;

            flags |= ((fsSelection & (ITALIC | OBLIQUE)) != 0) ? FlagsEnum.Italic : 0;

            switch (os2.FamilyClass)
            {
            case OS2WindowsMetricsTable.FAMILY_CLASS_CLAREDON_SERIFS:
            case OS2WindowsMetricsTable.FAMILY_CLASS_FREEFORM_SERIFS:
            case OS2WindowsMetricsTable.FAMILY_CLASS_MODERN_SERIFS:
            case OS2WindowsMetricsTable.FAMILY_CLASS_OLDSTYLE_SERIFS:
            case OS2WindowsMetricsTable.FAMILY_CLASS_SLAB_SERIFS:
                flags |= FlagsEnum.Serif;
                break;

            case OS2WindowsMetricsTable.FAMILY_CLASS_SCRIPTS:
                flags |= FlagsEnum.Script;
                break;

            default:
                break;
            }

            fd.FontWeight = os2.WeightClass;

            flags |= FlagsEnum.Symbolic;
            flags &= ~FlagsEnum.Nonsymbolic;

            fd.Flags = flags;
            // ItalicAngle
            fd.ItalicAngle = post.ItalicAngle;

            // FontBBox
            HeaderTable header  = ttf.Header;
            float       scaling = 1000f / header.UnitsPerEm;
            var         skRect  = new SKRect(
                header.XMin * scaling,
                header.YMin * scaling,
                header.XMax * scaling,
                header.YMax * scaling
                );


            Rectangle rect = new Rectangle(skRect);

            fd.FontBBox = rect;

            // Ascent, Descent
            HorizontalHeaderTable hHeader = ttf.HorizontalHeader;

            fd.Ascent  = hHeader.Ascender * scaling;
            fd.Descent = hHeader.Descender * scaling;

            // CapHeight, XHeight
            if (os2.Version >= 1.2)
            {
                fd.CapHeight = os2.CapHeight * scaling;
                fd.XHeight   = os2.Height * scaling;
            }
            else
            {
                var capHPath = ttf.GetPath("H");
                if (capHPath != null)
                {
                    fd.CapHeight = (float)Math.Round(capHPath.Bounds.Bottom * scaling);
                }
                else
                {
                    // estimate by summing the typographical +ve ascender and -ve descender
                    fd.CapHeight = os2.TypoAscender + (os2.TypoDescender * scaling);
                }
                var xPath = ttf.GetPath("x");
                if (xPath != null)
                {
                    fd.XHeight = (float)Math.Round(xPath.Bounds.Bottom * scaling);
                }
                else
                {
                    // estimate by halving the typographical ascender
                    fd.XHeight = os2.TypoAscender / (2.0f * scaling);
                }
            }

            // StemV - there's no true TTF equivalent of this, so we estimate it
            fd.StemV = skRect.Width * .13f;

            return(fd);
        }
Пример #13
0
 /**
  * Loads a TTF to be embedded into a document as a simple font.
  *
  * <p>
  * <b>Note:</b> Simple fonts only support 256 characters. For Unicode support, use
  * {@link PDType0Font#load(Document, Bytes.IInputStream)} instead.
  * </p>
  *
  * @param doc The PDF document that will hold the embedded font.
  * @param ttf A true type font
  * @param encoding The PostScript encoding vector to be used for embedding.
  * @return a PdfTrueTypeFont instance.
  * @throws IOException If there is an error loading the data.
  */
 public static PdfTrueTypeFont Load(Document doc, TrueTypeFont ttf, Encoding encoding)
 {
     return(new PdfTrueTypeFont(doc, ttf, encoding, false));
 }
Пример #14
0
 /**
  * Loads a TTF to be embedded into a document as a vertical Type 0 font.
  *
  * @param doc The PDF document that will hold the embedded font.
  * @param ttf A TrueType font.
  * @param embedSubset True if the font will be subset before embedding
  * @return A Type0 font with a CIDFontType2 descendant.
  * @throws IOException If there is an error reading the font stream.
  */
 public static PdfType0Font LoadVertical(Document doc, TrueTypeFont ttf, bool embedSubset)
 {
     return(new PdfType0Font(doc, ttf, embedSubset, false, true));
 }