protected void Put( int charCode, string charName ) { codes[new ByteArray(new byte[] { (byte)charCode })] = GlyphMapping.NameToCode(charName); }
protected void Put( int charCode, string charName ) { Put(charCode, GlyphMapping.NameToCode(charName).Value); }
static CffParser() { StandardCharsets = new Dictionary <StandardCharsetEnum, IDictionary <int, int> >(); foreach (StandardCharsetEnum charset in Enum.GetValues(typeof(StandardCharsetEnum))) { IDictionary <int, int> charsetMap = new Dictionary <int, int>(); using (StreamReader stream = new StreamReader( Assembly.GetExecutingAssembly().GetManifestResourceStream("fonts.cff." + charset.ToString() + "Charset") )) { String line; while ((line = stream.ReadLine()) != null) { string[] lineItems = line.Split(','); charsetMap[Int32.Parse(lineItems[0])] = GlyphMapping.NameToCode(lineItems[1]).Value; } } } StandardStrings = new List <string>(); using (StreamReader stream = new StreamReader( Assembly.GetExecutingAssembly().GetManifestResourceStream("fonts.cff.StandardStrings") )) { string line; while ((line = stream.ReadLine()) != null) { StandardStrings.Add(line); } } }
/** * <summary>Loads individual character metrics [AFM:4.1:3,4,4.4,8].</summary> */ private void LoadCharMetrics( ) { GlyphIndexes = new Dictionary <int, int>(); GlyphWidths = new Dictionary <int, int>(); string line; Regex linePattern = new Regex("C (\\S+) ; WX (\\S+) ; N (\\S+)"); int implicitCharCode = short.MaxValue; while ((line = FontData.ReadLine()) != null) { MatchCollection lineMatches = linePattern.Matches(line); if (lineMatches.Count < 1) { if (line.Equals("EndCharMetrics")) { break; } continue; } Match lineMatch = lineMatches[0]; int charCode = ConvertUtils.ParseIntInvariant(lineMatch.Groups[1].Value); int width = ConvertUtils.ParseAsIntInvariant(lineMatch.Groups[2].Value); string charName = lineMatch.Groups[3].Value; if (charCode < 0) { if (charName == null) { continue; } charCode = ++implicitCharCode; } int code = ( charName == null || Metrics.IsCustomEncoding ? charCode : GlyphMapping.NameToCode(charName).Value ); GlyphIndexes[code] = charCode; GlyphWidths[charCode] = width; } }
private int ToUnicode( int sid ) { /* * FIXME: avoid Unicode resolution at this stage -- names should be kept to allow subsequent * character substitution (see font differences) in case of custom (non-unicode) encodings. */ int?code = GlyphMapping.NameToCode(GetString(sid)); if (!code.HasValue) { //custom code code = sid; // really bad } return(code.Value); }
/** * <summary>Loads the encoding differences into the given collection.</summary> * <param name="encodingDictionary">Encoding dictionary.</param> * <param name="codes">Encoding to alter applying differences.</param> */ protected void LoadEncodingDifferences( PdfDictionary encodingDictionary, Dictionary <ByteArray, int> codes ) { PdfArray differenceObjects = (PdfArray)encodingDictionary.Resolve(PdfName.Differences); if (differenceObjects == null) { return; } /* * NOTE: Each code is the first index in a sequence of character codes to be changed. * The first character name after the code becomes the name corresponding to that code. * Subsequent names replace consecutive code indices until the next code appears * in the array or the array ends. */ byte[] charCodeData = new byte[1]; foreach (PdfDirectObject differenceObject in differenceObjects) { if (differenceObject is PdfInteger) { charCodeData[0] = (byte)(((int)((PdfInteger)differenceObject).Value) & 0xFF); } else // NOTE: MUST be PdfName. { ByteArray charCode = new ByteArray(charCodeData); string charName = (string)((PdfName)differenceObject).Value; if (charName.Equals(".notdef")) { codes.Remove(charCode); } else { try { codes[charCode] = GlyphMapping.NameToCode(charName); } catch { codes[charCode] = (int)charCodeData[0]; } // NOTE: This is an extreme remedy to non-standard character name lookups. } charCodeData[0]++; } } }
/** * <summary>Parses the character-code-to-unicode mapping [PDF:1.6:5.9.1].</summary> */ public Dictionary <ByteArray, int> Parse( ) { Dictionary <ByteArray, int> codes = new Dictionary <ByteArray, int>(); string line; Regex linePattern = new Regex("(\\S+)\\s+(.+)"); while ((line = stream.ReadLine()) != null) { MatchCollection lineMatches = linePattern.Matches(line); if (lineMatches.Count < 1) { continue; } Match lineMatch = lineMatches[0]; string key = lineMatch.Groups[1].Value; if (key.Equals("/Encoding")) { // Skip to the encoding array entries! stream.ReadLine(); string encodingLine; Regex encodingLinePattern = new Regex("dup (\\S+) (\\S+) put"); while ((encodingLine = stream.ReadLine()) != null) { MatchCollection encodingLineMatches = encodingLinePattern.Matches(encodingLine); if (encodingLineMatches.Count < 1) { break; } Match encodingLineMatch = encodingLineMatches[0]; byte[] inputCode = new byte[] { (byte)Int32.Parse(encodingLineMatch.Groups[1].Value) }; string name = encodingLineMatch.Groups[2].Value.Substring(1); codes[new ByteArray(inputCode)] = GlyphMapping.NameToCode(name).Value; } break; } } return(codes); }
/** * <summary>Converts the current token into its Unicode value.</summary> */ private int ParseUnicode( ) { switch (TokenType) { case TokenTypeEnum.Hex: // Character code in hexadecimal format. return(Int32.Parse((string)Token, NumberStyles.HexNumber)); case TokenTypeEnum.Integer: // Character code in plain format. return((int)Token); case TokenTypeEnum.Name: // Character name. return(GlyphMapping.NameToCode((string)Token).Value); default: throw new Exception( "Hex string, integer or name expected instead of " + TokenType ); } }
/** * <summary>Loads kerning data [AFM:4.1:3,4,4.5,9].</summary> */ private void LoadKerningData( ) { GlyphKernings = new Dictionary <int, int>(); string line; while ((line = FontData.ReadLine()) != null) { if (line.StartsWith("StartKernPairs")) { break; } } Regex linePattern = new Regex("KPX (\\S+) (\\S+) (\\S+)"); while ((line = FontData.ReadLine()) != null) { MatchCollection lineMatches = linePattern.Matches(line); if (lineMatches.Count < 1) { if (line.Equals("EndKernPairs")) { break; } continue; } Match lineMatch = lineMatches[0]; int code1 = GlyphMapping.NameToCode(lineMatch.Groups[1].Value).Value; int code2 = GlyphMapping.NameToCode(lineMatch.Groups[2].Value).Value; int pair = code1 << 16 + code2; int value = ConvertUtils.ParseAsIntInvariant(lineMatch.Groups[3].Value); GlyphKernings[pair] = value; } }
protected void LoadEncoding( ) { // Mapping character codes... PdfDataObject encodingObject = BaseDataObject.Resolve(PdfName.Encoding); FlagsEnum flags = Flags; symbolic = (flags & FlagsEnum.Symbolic) != 0; if (this.codes == null) { IDictionary <ByteArray, int> codes; if (encodingObject is PdfDictionary) // Derived encoding. { PdfDictionary encodingDictionary = (PdfDictionary)encodingObject; // Base encoding. codes = GetBaseEncoding((PdfName)encodingDictionary[PdfName.BaseEncoding]); // Differences. PdfArray differencesObject = (PdfArray)encodingDictionary.Resolve(PdfName.Differences); if (differencesObject != null) { /* * NOTE: Each code is the first index in a sequence of character codes to be changed: the * first character name after a code associates that character to that code; subsequent * names replace consecutive code indices until the next code appears in the array. */ byte[] charCodeData = new byte[1]; foreach (PdfDirectObject differenceObject in differencesObject) { if (differenceObject is PdfInteger) // Subsequence initial code. { charCodeData[0] = (byte)(((int)((PdfInteger)differenceObject).Value) & 0xFF); } else // Character name. { ByteArray charCode = new ByteArray(charCodeData); string charName = (string)((PdfName)differenceObject).Value; if (charName.Equals(".notdef")) { codes.Remove(charCode); } else { int?code = GlyphMapping.NameToCode(charName); codes[charCode] = (code ?? charCodeData[0]); } charCodeData[0]++; } } } } else // Predefined encoding. { codes = GetBaseEncoding((PdfName)encodingObject); } this.codes = new BiDictionary <ByteArray, int>(codes); } // Purging unused character codes... { PdfArray glyphWidthObjects = (PdfArray)BaseDataObject.Resolve(PdfName.Widths); if (glyphWidthObjects != null) { ByteArray charCode = new ByteArray(new byte[] { (byte)((PdfInteger)BaseDataObject[PdfName.FirstChar]).IntValue }); foreach (PdfDirectObject glyphWidthObject in glyphWidthObjects) { // PK 2017-03-08 - Changed type from PdfInteger to IPdfNumber to avoid ClassCastException and allow for more granular font sizes if (((IPdfNumber)glyphWidthObject).IntValue == 0) { codes.Remove(charCode); } charCode.Data[0]++; } } } // Mapping glyph indices... glyphIndexes = new Dictionary <int, int>(); foreach (KeyValuePair <ByteArray, int> code in codes) { glyphIndexes[code.Value] = (int)code.Key.Data[0] & 0xFF; } }
/** * <summary>Parses the character-code-to-unicode mapping [PDF:1.6:5.9.1].</summary> */ public IDictionary <ByteArray, int> Parse( ) { stream.Position = 0; IDictionary <ByteArray, int> codes = new Dictionary <ByteArray, int>(); { int itemCount = 0; try { while (MoveNext()) { switch (tokenType) { case TokenTypeEnum.Keyword: { string operator_ = (String)token; if (operator_.Equals(BeginBaseFontCharOperator) || operator_.Equals(BeginCIDCharOperator)) { /* * NOTE: The first element on each line is the input code of the template font; * the second element is the code or name of the character. */ for ( int itemIndex = 0; itemIndex < itemCount; itemIndex++ ) { // 1. Input code. MoveNext(); ByteArray inputCode = new ByteArray((byte[])token); // 2. Character... MoveNext(); switch (tokenType) { case TokenTypeEnum.Hex: // ...code (hex). codes[inputCode] = ConvertUtils.ByteArrayToInt((byte[])token); break; case TokenTypeEnum.Integer: // ...code (plain). codes[inputCode] = (int)token; break; case TokenTypeEnum.Name: // ...name. codes[inputCode] = GlyphMapping.NameToCode((String)token); break; default: throw new Exception( operator_ + " section syntax error: hex string, integer or name expected instead of " + tokenType ); } } } else if (operator_.Equals(BeginBaseFontRangeOperator) || operator_.Equals(BeginCIDRangeOperator)) { /* * NOTE: The first and second elements in each line are the beginning and * ending valid input codes for the template font; the third element is * the beginning character code for the range. */ for ( int itemIndex = 0; itemIndex < itemCount; itemIndex++ ) { // 1. Beginning input code. MoveNext(); byte[] beginInputCode = (byte[])token; // 2. Ending input code. MoveNext(); byte[] endInputCode = (byte[])token; // 3. Character codes. MoveNext(); switch (tokenType) { case TokenTypeEnum.Hex: case TokenTypeEnum.Integer: { byte[] inputCode = beginInputCode; int charCode; switch (tokenType) { case TokenTypeEnum.Hex: charCode = ConvertUtils.ByteArrayToInt((byte[])token); break; case TokenTypeEnum.Integer: charCode = (int)token; break; default: throw new Exception( operator_ + " section syntax error: hex string or integer expected instead of " + tokenType ); } int endCharCode = charCode + (ConvertUtils.ByteArrayToInt(endInputCode) - ConvertUtils.ByteArrayToInt(beginInputCode)); while (true) { codes[new ByteArray(inputCode)] = charCode; if (charCode == endCharCode) { break; } OperationUtils.Increment(inputCode); charCode++; } break; } case TokenTypeEnum.ArrayBegin: { byte[] inputCode = beginInputCode; while (MoveNext() && tokenType != TokenTypeEnum.ArrayEnd) { codes[new ByteArray(inputCode)] = GlyphMapping.NameToCode((String)token); OperationUtils.Increment(inputCode); } break; } default: throw new Exception( operator_ + " section syntax error: hex string, integer or name array expected instead of " + tokenType ); } } } break; } case TokenTypeEnum.Integer: { itemCount = (int)token; break; } } } } catch (FileFormatException fileFormatException) { throw new Exception("Failed character map parsing.", fileFormatException); } } return(codes); }