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; } } }
public static TTFStringMeasurer Create(TrueTypeFile forfont, CMapEncoding encoding, TypeMeasureOptions options) { HorizontalMetrics table = forfont.Directories["hmtx"].Table as HorizontalMetrics; CMAPTable cmap = forfont.Directories["cmap"].Table as CMAPTable; OS2Table os2 = forfont.Directories["OS/2"].Table as OS2Table; FontHeader head = forfont.Directories["head"].Table as FontHeader; HorizontalHeader hhead = forfont.Directories["hhea"].Table as HorizontalHeader; CMAPSubTable map = cmap.GetOffsetTable(encoding); if (map == null) { encoding = CMapEncoding.Unicode_20; map = cmap.GetOffsetTable(CMapEncoding.Unicode_20); } if (map == null) { encoding = CMapEncoding.MacRoman; map = cmap.GetOffsetTable(CMapEncoding.MacRoman); } return(new TTFStringMeasurer(head.UnitsPerEm, map, os2, hhead, table.HMetrics, forfont, encoding, options)); }
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 TTFStringMeasurer(int unitsPerEm, CMAPSubTable offsets, OS2Table oS2, HorizontalHeader hheader, List <HMetric> metrics, TrueTypeFile font, CMapEncoding encoding, TypeMeasureOptions options) { this._unitsPerEm = unitsPerEm; this._offsets = offsets; this._os2 = oS2; this._metrics = metrics; this._lookup = new Dictionary <char, HMetric>(); this._options = options; this._fontUseTypo = (oS2.Version >= OS2TableVersion.OpenType15) && ((oS2.Selection & FontSelection.UseTypographicSizes) > 0); this._hheader = hheader; this._fontfile = font; this._cMapEncoding = encoding; }
public virtual void TrueTypeFontAndCmapConstructorTest() { TrueTypeFont ttf = new TrueTypeFont(sourceFolder + "NotoSerif-Regular_v1.7.ttf"); PdfType0Font type0Font = new PdfType0Font(ttf, PdfEncodings.IDENTITY_H); CMapEncoding cmap = type0Font.GetCmap(); NUnit.Framework.Assert.IsNotNull(cmap); NUnit.Framework.Assert.IsTrue(cmap.IsDirect()); NUnit.Framework.Assert.IsFalse(cmap.HasUniMap()); NUnit.Framework.Assert.IsNull(cmap.GetUniMapName()); NUnit.Framework.Assert.AreEqual("Adobe", cmap.GetRegistry()); NUnit.Framework.Assert.AreEqual("Identity", cmap.GetOrdering()); NUnit.Framework.Assert.AreEqual(0, cmap.GetSupplement()); NUnit.Framework.Assert.AreEqual(PdfEncodings.IDENTITY_H, cmap.GetCmapName()); }
// Note. Make this constructor protected. Only PdfFontFactory (kernel level) will // be able to create Type0 font based on predefined font. // Or not? Possible it will be convenient construct PdfType0Font based on custom CidFont. // There is no typography features in CJK fonts. internal PdfType0Font(CidFont font, String cmap) : base() { if (!CidFontProperties.IsCidFont(font.GetFontNames().GetFontName(), cmap)) { throw new PdfException("Font {0} with {1} encoding is not a cjk font.").SetMessageParams(font.GetFontNames ().GetFontName(), cmap); } this.fontProgram = font; vertical = cmap.EndsWith("V"); String uniMap = GetCompatibleUniMap(fontProgram.GetRegistry()); cmapEncoding = new CMapEncoding(cmap, uniMap); longTag = new SortedSet <int>(); cidFontType = CID_FONT_TYPE_0; }
public PDFCompositeFontWidths(CMapEncoding encoding, CMAPSubTable cmap, HorizontalMetrics hmetrics, int unitsPerEm, int glyphUnits) { this.HMetrics = hmetrics; this.CharacterMappings = cmap; this.Encoding = encoding; this.UnitsPerEm = unitsPerEm; this.GlyphUnits = glyphUnits; _char2offset = new SortedDictionary <char, WidthMetric>(); _offset2char = new SortedDictionary <int, char>(); this.MinGlyphIndex = ushort.MaxValue; #if REGISTER_DEFAULT_GLYPHS //pre-load the glyph array as this.RegisterDefaultGlyphs(); #endif }
public virtual void DictionaryConstructorTest() { String filePath = sourceFolder + "documentWithType0Noto.pdf"; PdfDocument pdfDocument = new PdfDocument(new PdfReader(filePath)); PdfDictionary fontDict = pdfDocument.GetPage(1).GetResources().GetResource(PdfName.Font).GetAsDictionary(new PdfName("F1")); PdfType0Font type0Font = new PdfType0Font(fontDict); CMapEncoding cmap = type0Font.GetCmap(); NUnit.Framework.Assert.IsNotNull(cmap); NUnit.Framework.Assert.IsTrue(cmap.IsDirect()); NUnit.Framework.Assert.IsFalse(cmap.HasUniMap()); NUnit.Framework.Assert.IsNull(cmap.GetUniMapName()); NUnit.Framework.Assert.AreEqual("Adobe", cmap.GetRegistry()); NUnit.Framework.Assert.AreEqual("Identity", cmap.GetOrdering()); NUnit.Framework.Assert.AreEqual(0, cmap.GetSupplement()); NUnit.Framework.Assert.AreEqual(PdfEncodings.IDENTITY_H, cmap.GetCmapName()); }
internal PdfType0Font(CidFont font, String cmap) : base() { // Note. Make this constructor protected. Only PdfFontFactory (kernel level) will // be able to create Type0 font based on predefined font. // Or not? Possible it will be convenient construct PdfType0Font based on custom CidFont. // There is no typography features in CJK fonts. if (!CidFontProperties.IsCidFont(font.GetFontNames().GetFontName(), cmap)) { throw new PdfException("font.1.with.2.encoding.is.not.a.cjk.font").SetMessageParams(font.GetFontNames().GetFontName (), cmap); } this.fontProgram = font; vertical = cmap.EndsWith("V"); String uniMap = GetCompatibleUniMap(fontProgram.GetRegistry()); cmapEncoding = new CMapEncoding(cmap, uniMap); longTag = new LinkedDictionary <int, int[]>(); cidFontType = CID_FONT_TYPE_0; }
internal PdfType0Font(PdfDictionary fontDictionary) : base(fontDictionary) { CheckFontDictionary(fontDictionary, PdfName.Type0); newFont = false; PdfDictionary cidFont = fontDictionary.GetAsArray(PdfName.DescendantFonts).GetAsDictionary(0); String cmap = fontDictionary.GetAsName(PdfName.Encoding).GetValue(); if (PdfEncodings.IDENTITY_H.Equals(cmap) || PdfEncodings.IDENTITY_V.Equals(cmap)) { PdfObject toUnicode = fontDictionary.Get(PdfName.ToUnicode); CMapToUnicode toUnicodeCMap = FontUtil.ProcessToUnicode(toUnicode); if (toUnicodeCMap == null) { String uniMap = GetUniMapFromOrdering(GetOrdering(cidFont)); toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(uniMap); if (toUnicodeCMap == null) { toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(PdfEncodings.IDENTITY_H); ILogger logger = LoggerFactory.GetLogger(typeof(iText.Kernel.Font.PdfType0Font)); logger.Error(String.Format(LogMessageConstant.UNKNOWN_CMAP, uniMap)); } } fontProgram = DocTrueTypeFont.CreateFontProgram(cidFont, toUnicodeCMap); cmapEncoding = new CMapEncoding(cmap); System.Diagnostics.Debug.Assert(fontProgram is IDocFontProgram); embedded = ((IDocFontProgram)fontProgram).GetFontFile() != null; cidFontType = CID_FONT_TYPE_2; } else { String cidFontName = cidFont.GetAsName(PdfName.BaseFont).GetValue(); String uniMap = GetUniMapFromOrdering(GetOrdering(cidFont)); if (uniMap != null && uniMap.StartsWith("Uni") && CidFontProperties.IsCidFont(cidFontName, uniMap)) { try { fontProgram = FontProgramFactory.CreateFont(cidFontName); cmapEncoding = new CMapEncoding(cmap, uniMap); embedded = false; } catch (System.IO.IOException) { fontProgram = null; cmapEncoding = null; } } else { CMapToUnicode toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(uniMap); if (toUnicodeCMap != null) { fontProgram = DocTrueTypeFont.CreateFontProgram(cidFont, toUnicodeCMap); cmapEncoding = new CMapEncoding(cmap, uniMap); } } if (fontProgram == null) { throw new PdfException(String.Format("Cannot recognise document font {0} with {1} encoding", cidFontName, cmap)); } cidFontType = CID_FONT_TYPE_0; } longTag = new LinkedDictionary <int, int[]>(); subset = false; }
public LineSize MeasureString(CMapEncoding encoding, string s, int startOffset, double emsize, double available, bool wordboundary, out int charsfitted, FontUnitType useUnits = FontUnitType.UseFontPreference) { HorizontalMetrics table = this.Directories["hmtx"].Table as HorizontalMetrics; CMAPTable cmap = this.Directories["cmap"].Table as CMAPTable; OS2Table os2 = this.Directories["OS/2"].Table as OS2Table; CMAPSubTable mac = cmap.GetOffsetTable(encoding); if (mac == null) { mac = cmap.GetOffsetTable(CMapEncoding.MacRoman); } HorizontalHeader hhead = this.Directories["hhea"].Table as HorizontalHeader; FontHeader head = this.Directories["head"].Table as FontHeader; available = (available * head.UnitsPerEm) / emsize; double len = 0.0; double lastwordlen = 0.0; int lastwordcount = 0; charsfitted = 0; for (int i = startOffset; i < s.Length; i++) { char c = s[i]; if (char.IsWhiteSpace(c)) { lastwordlen = len; lastwordcount = charsfitted; } int moffset = (int)mac.GetCharacterGlyphOffset(c); //System.Diagnostics.Debug.WriteLine("Character '" + chars[i].ToString() + "' (" + ((byte)chars[i]).ToString() + ") has offset '" + moffset.ToString() + "' in mac encoding and '" + woffset + "' in windows encoding"); if (moffset >= table.HMetrics.Count) { moffset = table.HMetrics.Count - 1; } Scryber.OpenType.SubTables.HMetric metric; metric = table.HMetrics[moffset]; if (i == 0) { len = -metric.LeftSideBearing; } len += metric.AdvanceWidth; //check if we can fit more if (len > available) { len -= metric.AdvanceWidth; break; } charsfitted++; } bool isboundary = false; if ((charsfitted + startOffset < s.Length) && wordboundary && lastwordlen > 0) { len = lastwordlen; charsfitted = lastwordcount; isboundary = true; } len = len / (double)head.UnitsPerEm; len = len * emsize; double h = GetLineHeight(useUnits, os2, hhead, head, emsize); return(new LineSize((float)len, (float)h, charsfitted, startOffset, isboundary)); }
/// <summary> /// Measures the size of the provided string at the specified font size (starting at a specific offset), /// stopping when the available space is full and returning the number of characters fitted. /// </summary> /// <param name="encoding">The encoding to use to map the characters</param> /// <param name="s">The string to measure the size of</param> /// <param name="startOffset">The starting (zero based) offset in that string to start measuring from</param> /// <param name="emsize">The M size in font units</param> /// <param name="availablePts">The max width allowed for this string</param> /// <param name="wordspace">The spacing between words in font units. Default 0</param> /// <param name="charspace">The spacing between characters in font units. Default 0</param> /// <param name="hscale">The horizontal scaling of all characters. Default 100</param> /// <param name="vertical">If true then this is vertical writing</param> /// <param name="wordboundary">If True the measuring will stop at a boundary to a word rather than character.</param> /// <param name="charsfitted">Set to the number of characters that can be renered at this size within the width.</param> /// <returns></returns> public LineSize MeasureString(CMapEncoding encoding, string s, int startOffset, double emsize, double availablePts, double?wordspacePts, double charspacePts, double hscale, bool vertical, bool wordboundary, out int charsfitted, FontUnitType useUnits = FontUnitType.UseFontPreference) { HorizontalMetrics table = this.Directories["hmtx"].Table as HorizontalMetrics; CMAPTable cmap = this.Directories["cmap"].Table as CMAPTable; OS2Table os2 = this.Directories["OS/2"].Table as OS2Table; CMAPSubTable mac = cmap.GetOffsetTable(encoding); if (mac == null) { mac = cmap.GetOffsetTable(CMapEncoding.MacRoman); } HorizontalHeader hhead = this.Directories["hhea"].Table as HorizontalHeader; FontHeader head = this.Directories["head"].Table as FontHeader; double availableFU = availablePts * ((double)head.UnitsPerEm / emsize); double charspaceFU = NoCharacterSpace; if (charspacePts != NoCharacterSpace) { charspaceFU = charspacePts * ((double)head.UnitsPerEm / emsize); } double wordspaceFU = NoWordSpace; if (wordspacePts.HasValue) { wordspaceFU = (wordspacePts.Value * ((double)head.UnitsPerEm / emsize)); } else if (charspacePts != NoCharacterSpace) { //If we dont have explicit wordspacing then we use the character spacing wordspaceFU = charspaceFU; } double len = 0.0; double lastwordlen = 0.0; int lastwordcount = 0; charsfitted = 0; for (int i = startOffset; i < s.Length; i++) { char c = s[i]; if (char.IsWhiteSpace(c)) { lastwordlen = len; lastwordcount = charsfitted; } int moffset = (int)mac.GetCharacterGlyphOffset(c); if (moffset >= table.HMetrics.Count) { moffset = table.HMetrics.Count - 1; } Scryber.OpenType.SubTables.HMetric metric; metric = table.HMetrics[moffset]; double w = metric.AdvanceWidth; if (i == 0) { w -= metric.LeftSideBearing; } if (c == ' ') { if (wordspaceFU != NoWordSpace) { w += wordspaceFU; } } else if (charspaceFU != NoCharacterSpace) { w += charspaceFU; } if (hscale != NoHorizontalScale) { w *= hscale; } len += w; //check if we can fit more if (len > availableFU) { len -= w; break; } charsfitted++; } bool isboundary = false; if ((charsfitted + startOffset < s.Length) && wordboundary && lastwordlen > 0) { len = lastwordlen; charsfitted = lastwordcount; isboundary = true; } len = len * emsize; len = len / (double)head.UnitsPerEm; double h = GetLineHeight(useUnits, os2, hhead, head, emsize); return(new LineSize(len, h, charsfitted, startOffset, isboundary)); }
public bool HasCMap(CMapEncoding encoding) { CMAPSubTable tbl = this.Tables.CMap.GetOffsetTable(encoding); return(null != tbl); }
internal PdfType0Font(PdfDictionary fontDictionary) : base(fontDictionary) { newFont = false; PdfDictionary cidFont = fontDictionary.GetAsArray(PdfName.DescendantFonts).GetAsDictionary(0); PdfObject cmap = fontDictionary.Get(PdfName.Encoding); PdfObject toUnicode = fontDictionary.Get(PdfName.ToUnicode); CMapToUnicode toUnicodeCMap = FontUtil.ProcessToUnicode(toUnicode); if (cmap.IsName() && (PdfEncodings.IDENTITY_H.Equals(((PdfName)cmap).GetValue()) || PdfEncodings.IDENTITY_V .Equals(((PdfName)cmap).GetValue()))) { if (toUnicodeCMap == null) { String uniMap = GetUniMapFromOrdering(GetOrdering(cidFont)); toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(uniMap); if (toUnicodeCMap == null) { toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(PdfEncodings.IDENTITY_H); ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Font.PdfType0Font)); logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.UNKNOWN_CMAP, uniMap)); } } fontProgram = DocTrueTypeFont.CreateFontProgram(cidFont, toUnicodeCMap); cmapEncoding = CreateCMap(cmap, null); System.Diagnostics.Debug.Assert(fontProgram is IDocFontProgram); embedded = ((IDocFontProgram)fontProgram).GetFontFile() != null; } else { String cidFontName = cidFont.GetAsName(PdfName.BaseFont).GetValue(); String uniMap = GetUniMapFromOrdering(GetOrdering(cidFont)); if (uniMap != null && uniMap.StartsWith("Uni") && CidFontProperties.IsCidFont(cidFontName, uniMap)) { try { fontProgram = FontProgramFactory.CreateFont(cidFontName); cmapEncoding = CreateCMap(cmap, uniMap); embedded = false; } catch (System.IO.IOException) { fontProgram = null; cmapEncoding = null; } } else { if (toUnicodeCMap == null) { toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(uniMap); } if (toUnicodeCMap != null) { fontProgram = DocTrueTypeFont.CreateFontProgram(cidFont, toUnicodeCMap); cmapEncoding = CreateCMap(cmap, uniMap); } } if (fontProgram == null) { throw new PdfException(MessageFormatUtil.Format(PdfException.CannotRecogniseDocumentFontWithEncoding, cidFontName , cmap)); } } // DescendantFonts is a one-element array specifying the CIDFont dictionary that is the descendant of this Type 0 font. PdfDictionary cidFontDictionary = fontDictionary.GetAsArray(PdfName.DescendantFonts).GetAsDictionary(0); // Required according to the spec PdfName subtype = cidFontDictionary.GetAsName(PdfName.Subtype); if (PdfName.CIDFontType0.Equals(subtype)) { cidFontType = CID_FONT_TYPE_0; } else { if (PdfName.CIDFontType2.Equals(subtype)) { cidFontType = CID_FONT_TYPE_2; } else { LogManager.GetLogger(GetType()).Error(iText.IO.LogMessageConstant.FAILED_TO_DETERMINE_CID_FONT_SUBTYPE); } } longTag = new SortedSet <int>(); subset = false; }