internal Type2Font( Document context, OpenFontParser parser ) : base(context,parser) { }
internal CompositeFont( Document context, OpenFontParser parser ) : base(context) { Load(parser); }
protected override void LoadEncoding( ) { OpenFontParser parser; { PdfDictionary descriptor = Descriptor; if(descriptor.ContainsKey(PdfName.FontFile2)) // Embedded TrueType font file (without 'glyf' table). { PdfStream fontFileStream = (PdfStream)descriptor.Resolve(PdfName.FontFile2); parser = new OpenFontParser(fontFileStream.Body); } else if(descriptor.ContainsKey(PdfName.FontFile3)) { PdfStream fontFileStream = (PdfStream)descriptor.Resolve(PdfName.FontFile3); PdfName fontFileSubtype = (PdfName)fontFileStream.Header[PdfName.Subtype]; if(fontFileSubtype.Equals(PdfName.OpenType)) // Embedded OpenFont/TrueType font file (with 'glyf' table). {parser = new OpenFontParser(fontFileStream.Body);} else // Unknown. throw new NotSupportedException("Unknown embedded font file format: " + fontFileSubtype); } else {parser = null;} } if(parser != null) // Embedded font file. { // Glyph indexes. glyphIndexes = parser.GlyphIndexes; if(codes != null && parser.Metrics.IsCustomEncoding) { /* NOTE: In case of symbolic font, glyph indices are natively mapped to character codes, so they must be remapped to Unicode whenever possible (i.e. when ToUnicode stream is available). */ Dictionary<int,int> unicodeGlyphIndexes = new Dictionary<int,int>(); foreach(KeyValuePair<int,int> glyphIndexEntry in glyphIndexes) { int code; if(!codes.TryGetValue(new ByteArray(new byte[]{(byte)(int)glyphIndexEntry.Key}),out code)) continue; unicodeGlyphIndexes[code] = glyphIndexEntry.Value; } glyphIndexes = unicodeGlyphIndexes; } } PdfDataObject encodingObject = BaseDataObject.Resolve(PdfName.Encoding); FlagsEnum flags = Flags; if((flags & FlagsEnum.Symbolic) != 0 || ((flags & FlagsEnum.Nonsymbolic) == 0 && encodingObject == null)) // Symbolic. { symbolic = true; if(glyphIndexes == null) { /* NOTE: In case no font file is available, we have to synthesize its metrics from existing entries. */ glyphIndexes = new Dictionary<int,int>(); PdfArray glyphWidthObjects = (PdfArray)BaseDataObject.Resolve(PdfName.Widths); if(glyphWidthObjects != null) { int code = ((PdfInteger)BaseDataObject[PdfName.FirstChar]).RawValue; foreach(PdfDirectObject glyphWidthObject in glyphWidthObjects) { if(((PdfInteger)glyphWidthObject).RawValue > 0) {glyphIndexes[code] = code;} code++; } } } if(this.codes == null) { Dictionary<ByteArray,int> codes = new Dictionary<ByteArray,int>(); foreach(KeyValuePair<int,int> glyphIndexEntry in glyphIndexes) { if(glyphIndexEntry.Value > 0) { int glyphCharCode = glyphIndexEntry.Key; byte[] charCode = new byte[]{(byte)glyphCharCode}; codes[new ByteArray(charCode)] = glyphCharCode; } } this.codes = new BiDictionary<ByteArray,int>(codes); } } else // Nonsymbolic. { symbolic = false; if(this.codes == null) { Dictionary<ByteArray,int> codes; if(encodingObject == null) // Default encoding. {codes = Encoding.Get(PdfName.StandardEncoding).GetCodes();} else if(encodingObject is PdfName) // Predefined encoding. {codes = Encoding.Get((PdfName)encodingObject).GetCodes();} else // Custom encoding. { PdfDictionary encodingDictionary = (PdfDictionary)encodingObject; // 1. Base encoding. PdfName baseEncodingName = (PdfName)encodingDictionary[PdfName.BaseEncoding]; if(baseEncodingName == null) // Default base encoding. {codes = Encoding.Get(PdfName.StandardEncoding).GetCodes();} else // Predefined base encoding. {codes = Encoding.Get(baseEncodingName).GetCodes();} // 2. Differences. LoadEncodingDifferences(encodingDictionary, codes); } this.codes = new BiDictionary<ByteArray,int>(codes); } if(glyphIndexes == null) { /* NOTE: In case no font file is available, we have to synthesize its metrics from existing entries. */ glyphIndexes = new Dictionary<int,int>(); PdfArray glyphWidthObjects = (PdfArray)BaseDataObject.Resolve(PdfName.Widths); if(glyphWidthObjects != null) { ByteArray charCode = new ByteArray( new byte[] {(byte)(int)((PdfInteger)BaseDataObject[PdfName.FirstChar]).RawValue} ); foreach(PdfDirectObject glyphWidthObject in glyphWidthObjects) { if(((PdfInteger)glyphWidthObject).RawValue > 0) { int code; if(codes.TryGetValue(charCode,out code)) {glyphIndexes[code] = (int)charCode.Data[0];} } charCode.Data[0]++; } } } } }
public static new CompositeFont Get( Document context, bytes::IInputStream fontData ) { OpenFontParser parser = new OpenFontParser(fontData); switch(parser.OutlineFormat) { case OpenFontParser.OutlineFormatEnum.CFF: return new Type0Font(context,parser); case OpenFontParser.OutlineFormatEnum.TrueType: return new Type2Font(context,parser); } throw new NotSupportedException("Unknown composite font format."); }
/** <summary>Creates the font descriptor.</summary> */ private PdfReference Load_CreateFontDescriptor( OpenFontParser parser ) { PdfDictionary fontDescriptor = new PdfDictionary(); { OpenFontParser.FontMetrics metrics = parser.Metrics; // Type. fontDescriptor[PdfName.Type] = PdfName.FontDescriptor; // FontName. fontDescriptor[PdfName.FontName] = BaseDataObject[PdfName.BaseFont]; // Flags [PDF:1.6:5.7.1]. FlagsEnum flags = 0; if(metrics.IsFixedPitch) {flags |= FlagsEnum.FixedPitch;} if(metrics.IsCustomEncoding) {flags |= FlagsEnum.Symbolic;} else {flags |= FlagsEnum.Nonsymbolic;} fontDescriptor[PdfName.Flags] = PdfInteger.Get(Convert.ToInt32(flags)); // FontBBox. fontDescriptor[PdfName.FontBBox] = new Rectangle( new drawing::PointF(metrics.XMin * metrics.UnitNorm, metrics.YMin * metrics.UnitNorm), new drawing::PointF(metrics.XMax * metrics.UnitNorm, metrics.YMax * metrics.UnitNorm) ).BaseDataObject; // ItalicAngle. fontDescriptor[PdfName.ItalicAngle] = PdfReal.Get(metrics.ItalicAngle); // Ascent. fontDescriptor[PdfName.Ascent] = PdfReal.Get( metrics.Ascender == 0 ? metrics.STypoAscender * metrics.UnitNorm : metrics.Ascender * metrics.UnitNorm ); // Descent. fontDescriptor[PdfName.Descent] = PdfReal.Get( metrics.Descender == 0 ? metrics.STypoDescender * metrics.UnitNorm : metrics.Descender * metrics.UnitNorm ); // Leading. fontDescriptor[PdfName.Leading] = PdfReal.Get(metrics.STypoLineGap * metrics.UnitNorm); // CapHeight. fontDescriptor[PdfName.CapHeight] = PdfReal.Get(metrics.SCapHeight * metrics.UnitNorm); // StemV. /* NOTE: '100' is just a rule-of-thumb value, 'cause I've still to solve the 'cvt' table puzzle (such a harsh headache!) for TrueType fonts... TODO:IMPL TrueType and CFF stemv real value to extract!!! */ fontDescriptor[PdfName.StemV] = PdfInteger.Get(100); // FontFile. fontDescriptor[PdfName.FontFile2] = File.Register( new PdfStream(new bytes::Buffer(parser.FontData.ToByteArray())) ); } return File.Register(fontDescriptor); }
/** <summary>Loads the font data.</summary> */ private void Load( OpenFontParser parser ) { glyphIndexes = parser.GlyphIndexes; glyphKernings = parser.GlyphKernings; glyphWidths = parser.GlyphWidths; PdfDictionary baseDataObject = BaseDataObject; // BaseFont. baseDataObject[PdfName.BaseFont] = new PdfName(parser.FontName); // Subtype. baseDataObject[PdfName.Subtype] = PdfName.Type0; // Encoding. baseDataObject[PdfName.Encoding] = PdfName.IdentityH; //TODO: this is a simplification (to refine later). // Descendant font. PdfDictionary cidFontDictionary = new PdfDictionary( new PdfName[]{PdfName.Type}, new PdfDirectObject[]{PdfName.Font} ); // CIDFont dictionary [PDF:1.6:5.6.3]. { // Subtype. PdfName subType; switch(parser.OutlineFormat) { case OpenFontParser.OutlineFormatEnum.TrueType: subType = PdfName.CIDFontType2; break; case OpenFontParser.OutlineFormatEnum.CFF: subType = PdfName.CIDFontType0; break; default: throw new NotImplementedException(); } cidFontDictionary[PdfName.Subtype] = subType; // BaseFont. cidFontDictionary[PdfName.BaseFont] = new PdfName(parser.FontName); // CIDSystemInfo. cidFontDictionary[PdfName.CIDSystemInfo] = new PdfDictionary( new PdfName[] { PdfName.Registry, PdfName.Ordering, PdfName.Supplement }, new PdfDirectObject[] { new PdfTextString("Adobe"), new PdfTextString("Identity"), PdfInteger.Get(0) } ); // Generic predefined CMap (Identity-H/V (Adobe-Identity-0)) [PDF:1.6:5.6.4]. // FontDescriptor. cidFontDictionary[PdfName.FontDescriptor] = Load_CreateFontDescriptor(parser); // Encoding. Load_CreateEncoding(baseDataObject,cidFontDictionary); } baseDataObject[PdfName.DescendantFonts] = new PdfArray(new PdfDirectObject[]{File.Register(cidFontDictionary)}); Load(); }