/** * Reads a binary CharString. */ private Token ReadCharString(int length) { buffer.ReadByte(); // space byte[] data = new byte[length]; buffer.Read(data); return(new Token(data, TokenKind.CHARSTRING)); }
public static ICCProfile Load(byte[] data) { var profile = new ICCProfile(); var header = new ICCHeader(); var buffer = new Bytes.Buffer(data); header.ProfileSize = buffer.ReadUnsignedInt(); header.CMMTypeSignature = buffer.ReadUnsignedInt(); header.ProfileVersionNumber.Major = (byte)buffer.ReadByte(); header.ProfileVersionNumber.Minor = (byte)buffer.ReadByte(); header.ProfileVersionNumber.Reserv1 = (byte)buffer.ReadByte(); header.ProfileVersionNumber.Reserv2 = (byte)buffer.ReadByte(); header.ProfileDeviceClassSignature = (ICCProfileDeviceSignatures)buffer.ReadUnsignedInt(); header.ColorSpaceOfData = (ICCColorSpaceSignatures)buffer.ReadUnsignedInt(); header.ProfileConnectionSpace = (ICCColorSpaceSignatures)buffer.ReadUnsignedInt(); header.DateCreated.Load(buffer); header.acsp = buffer.ReadUnsignedInt(); header.PrimaryPlatformSignature = (ICCPrimaryPlatformSignatures)buffer.ReadUnsignedInt(); header.Flags = (ICCProfileFlags)buffer.ReadUnsignedInt(); header.DeviceManufacturer = buffer.ReadUnsignedInt(); header.DeviceModel = buffer.ReadUnsignedInt(); header.DeviceAttributes.Load(buffer); header.RenderingIntent.Intents = buffer.ReadUnsignedShort(); header.RenderingIntent.Reserved = buffer.ReadUnsignedShort(); header.XYZ.Load(buffer); header.ProfileCreatorSignature = buffer.ReadUnsignedInt(); header.FutureUse = new byte[44]; buffer.Read(header.FutureUse); profile.Header = header; var tagCount = buffer.ReadUnsignedInt(); for (int i = 0; i < tagCount; i++) { var tag = new ICCTagTable(); tag.Signature = (ICCTagTypes)buffer.ReadUnsignedInt(); tag.Offset = buffer.ReadUnsignedInt(); tag.ElementSize = buffer.ReadUnsignedInt(); profile.Tags[tag.Signature] = tag; } foreach (var tagTable in profile.Tags.Values) { buffer.Seek(tagTable.Offset); var key = buffer.ReadUnsignedInt(); if (Types.TryGetValue(key, out var type)) { tagTable.Tag = (ICCTag)Activator.CreateInstance(type, tagTable); tagTable.Tag.Profile = profile; tagTable.Tag.Load(buffer); } } return(profile); }
/** * Read the pdf input. * @param in The input. * @return Returns the pdf-array. * @throws IOException if an IO-error occurs. */ private byte[] ReadPfbInput(Bytes.Buffer input) { // copy into an array using (var output = new MemoryStream()) { byte[] tmpbuf = new byte[BUFFER_SIZE]; int amountRead = -1; while ((amountRead = input.Read(tmpbuf)) > 0) { output.Write(tmpbuf, 0, amountRead); } return(output.ToArray()); } }
private long CopyBytes(Bytes.Buffer input, Stream os, long newOffset, long lastOffset, int count) { // skip over from last original offset long nskip = newOffset - lastOffset; if (nskip != input.Skip(nskip)) { throw new EndOfStreamException("Unexpected EOF exception parsing glyphId of hmtx table."); } byte[] buf = new byte[count]; if (count != input.Read(buf, 0, count)) { throw new EndOfStreamException("Unexpected EOF exception parsing glyphId of hmtx table."); } os.Write(buf, 0, count); return(newOffset + count); }
/** * Parse the pfb-array. * @param pfb The pfb-Array * @throws IOException in an IO-error occurs. */ private void ParsePfb(byte[] pfb) { using (var input = new Bytes.Buffer(pfb)) { pfbdata = new byte[pfb.Length - PFB_HEADER_LENGTH]; lengths = new int[PFB_RECORDS.Length]; int pointer = 0; for (int records = 0; records < PFB_RECORDS.Length; records++) { if (input.ReadByte() != START_MARKER) { throw new IOException("Start marker missing"); } if (input.ReadByte() != PFB_RECORDS[records]) { throw new IOException("Incorrect record type"); } int size = input.ReadByte(); size += input.ReadByte() << 8; size += input.ReadByte() << 16; size += input.ReadByte() << 24; lengths[records] = size; if (pointer >= pfbdata.Length) { throw new EndOfStreamException("attempted to read past EOF"); } int got = input.Read(pfbdata, pointer, size); if (got < 0) { throw new EndOfStreamException(); } pointer += got; } } }
// never returns null private byte[] BuildGlyfTable(long[] newOffsets) { GlyphTable g = ttf.Glyph; long[] offsets = ttf.IndexToLocation.Offsets; MemoryStream bos = new MemoryStream(); using (Bytes.Buffer input = ttf.OriginalData) { long isResult = input.Skip(g.Offset); if (isResult.CompareTo(g.Offset) != 0) { Debug.WriteLine($"debug: Tried skipping {g.Offset} bytes but skipped only {isResult} bytes"); } long prevEnd = 0; // previously read glyph offset long newOffset = 0; // new offset for the glyph in the subset font int newGid = 0; // new GID in subset font // for each glyph in the subset foreach (int gid in glyphIds) { long offset = offsets[gid]; long length = offsets[gid + 1] - offset; newOffsets[newGid++] = newOffset; isResult = input.Skip(offset - prevEnd); if (isResult.CompareTo(offset - prevEnd) != 0) { Debug.WriteLine($"debug: Tried skipping {(offset - prevEnd)} bytes but skipped only {isResult} bytes"); } sbyte[] buf = new sbyte[(int)length]; isResult = input.Read(buf); if (isResult.CompareTo(length) != 0) { Debug.WriteLine($"debug: Tried reading {length} bytes but only {isResult} bytes read"); } // detect glyph type if (buf.Length >= 2 && buf[0] == -1 && buf[1] == -1) { // compound glyph int off = 2 * 5; int flags; do { // flags flags = (buf[off] & 0xff) << 8 | buf[off + 1] & 0xff; off += 2; // glyphIndex int componentGid = (buf[off] & 0xff) << 8 | buf[off + 1] & 0xff; if (!glyphIds.Contains(componentGid)) { glyphIds.Add(componentGid); } int newComponentGid = GetNewGlyphId(componentGid); buf[off] = (sbyte)((uint)(newComponentGid) >> 8); buf[off + 1] = (sbyte)newComponentGid; off += 2; // ARG_1_AND_2_ARE_WORDS if ((flags & 1 << 0) != 0) { off += 2 * 2; } else { off += 2; } // WE_HAVE_A_TWO_BY_TWO if ((flags & 1 << 7) != 0) { off += 2 * 4; } // WE_HAVE_AN_X_AND_Y_SCALE else if ((flags & 1 << 6) != 0) { off += 2 * 2; } // WE_HAVE_A_SCALE else if ((flags & 1 << 3) != 0) { off += 2; } }while ((flags & 1 << 5) != 0); // MORE_COMPONENTS // WE_HAVE_INSTRUCTIONS if ((flags & 0x0100) == 0x0100) { // USHORT numInstr int numInstr = (buf[off] & 0xff) << 8 | buf[off + 1] & 0xff; off += 2; // BYTE instr[numInstr] off += numInstr; } // write the compound glyph bos.Write((byte[])(Array)buf, 0, off); // offset to start next glyph newOffset += off; } else if (buf.Length > 0) { // copy the entire glyph bos.Write((byte[])(Array)buf, 0, buf.Length); // offset to start next glyph newOffset += buf.Length; } // 4-byte alignment if (newOffset % 4 != 0) { int len = 4 - (int)(newOffset % 4); bos.Write(PAD_BUF, 0, len); newOffset += len; } prevEnd = offset + length; } newOffsets[newGid++] = newOffset; } return(bos.ToArray()); }
/** * Resolve compound glyph references. */ private void AddCompoundReferences() { if (hasAddedCompoundReferences) { return; } hasAddedCompoundReferences = true; bool hasNested; do { GlyphTable g = ttf.Glyph; long[] offsets = ttf.IndexToLocation.Offsets; Bytes.Buffer input = ttf.OriginalData; ISet <int> glyphIdsToAdd = null; try { long isResult = input.Skip(g.Offset); if (isResult.CompareTo(g.Offset) != 0) { Debug.WriteLine($"debug: Tried skipping {g.Offset} bytes but skipped only {isResult} bytes"); } long lastOff = 0L; foreach (int glyphId in glyphIds) { long offset = offsets[glyphId]; long len = offsets[glyphId + 1] - offset; isResult = input.Skip(offset - lastOff); if (isResult.CompareTo(offset - lastOff) != 0) { Debug.WriteLine($"debug: Tried skipping {(offset - lastOff)} bytes but skipped only {isResult} bytes"); } sbyte[] buf = new sbyte[(int)len]; isResult = input.Read(buf); if (isResult.CompareTo(len) != 0) { Debug.WriteLine($"debug: Tried reading {len} bytes but only {isResult} bytes read"); } // rewrite glyphIds for compound glyphs if (buf.Length >= 2 && buf[0] == -1 && buf[1] == -1) { int off = 2 * 5; int flags; do { flags = (buf[off] & 0xff) << 8 | buf[off + 1] & 0xff; off += 2; int ogid = (buf[off] & 0xff) << 8 | buf[off + 1] & 0xff; if (!glyphIds.Contains(ogid)) { if (glyphIdsToAdd == null) { glyphIdsToAdd = new HashSet <int>(); } glyphIdsToAdd.Add(ogid); } off += 2; // ARG_1_AND_2_ARE_WORDS if ((flags & 1 << 0) != 0) { off += 2 * 2; } else { off += 2; } // WE_HAVE_A_TWO_BY_TWO if ((flags & 1 << 7) != 0) { off += 2 * 4; } // WE_HAVE_AN_X_AND_Y_SCALE else if ((flags & 1 << 6) != 0) { off += 2 * 2; } // WE_HAVE_A_SCALE else if ((flags & 1 << 3) != 0) { off += 2; } }while ((flags & 1 << 5) != 0); // MORE_COMPONENTS } lastOff = offsets[glyphId + 1]; } } finally { input.Dispose(); } if (glyphIdsToAdd != null) { glyphIds.AddAll(glyphIdsToAdd); } hasNested = glyphIdsToAdd != null; }while (hasNested); }