public void Write(Stream file, Document doc) { ObjectReference fileref = doc.GetReference(this); fileref.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(fileref.Id); sb.Append(" obj\r\n<<"); sb.Append("/Filter /FlateDecode\r\n"); Stream compressed = Compression.Compress(_bits); sb.Append("/Length "); sb.Append(compressed.Length); sb.Append(" /Length1 "); sb.Append(compressed.Length); sb.Append(">>\r\n"); sb.Append("stream\r\n"); Document.WriteData(file, sb.ToString()); compressed.CopyTo(file); sb.Clear(); sb.Append("\r\nendstream\r\nendobj\r\n"); Document.WriteData(file, sb.ToString()); }
public void Write(Stream file, Document doc, ushort unitsPerEm) { ObjectReference wref = doc.GetReference(this); wref.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(wref.Id); sb.Append(" obj\r\n[ "); // Each entry in the array is of one of these formats: // // c [ w1 w2 ... wn ] - for individual widths // c1 cn w - for a range of same widths // // At least for the proof of concept let's just do it // the easy way and specify each individual width. for (int x = 0; x < _widths.Length; ++x) { sb.Append(x); sb.Append("["); // The raw widths are in font units, but we want thousandths // of a text unit in the dictionary. See page 414. sb.Append(_widths[x] * 1000 / unitsPerEm); sb.Append("] "); } sb.Append(" ]\r\nendobj\r\n"); Document.WriteData(file, sb.ToString()); }
public void Write(Stream file, ObjectReference reference, Document doc) { reference.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(reference.Id); sb.Append(" obj\r\n"); sb.Append("<<\r\n"); sb.Append("/Type /Pages\r\n"); sb.Append("/Kids [ "); foreach (Page page in this) { ObjectReference pageref = doc.GetReference(page); sb.Append(pageref.Reference); sb.Append(" "); } sb.Append(" ]\r\n"); sb.Append("/Count "); sb.Append(this.Count); sb.Append("\r\n"); // sb.Append("/MediaBox "); // sb.Append(generator.Document.DefaultPageSize.Specification); // sb.Append("\r\n"); sb.Append(">>\r\n"); sb.Append("endobj\r\n"); Document.WriteData(file, sb.ToString()); }
public void Write(Stream file, ObjectReference streamRef, List <ContentFragment> fragments) { streamRef.ByteOffset = file.Position; // We need to know the full length of the stream so that we can // write it into the object header byte[] fullStream = new byte[0]; foreach (ContentFragment fragment in fragments) { int pos = fullStream.Length; byte[] fragStream = fragment.GetStream(); int length = fullStream.Length + fragStream.Length; System.Array.Resize(ref fullStream, length); fragStream.CopyTo(fullStream, pos); } StringBuilder sb = new StringBuilder(); sb.Append(streamRef.Id); sb.Append(" obj\r\n<</Length "); sb.Append(fullStream.Length); sb.Append(">>\r\nstream\r\n"); Document.WriteData(file, sb.ToString()); file.Write(fullStream, 0, fullStream.Length); Document.WriteData(file, "\r\nendstream\r\nendobj\r\n"); }
public override void Write(Stream file, Document doc) { ObjectReference fontref = doc.GetReference(this); fontref.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(fontref.Id); sb.Append(" obj\r\n"); sb.Append("<<\r\n/Type /Font\r\n"); sb.Append("/Subtype /Type1\r\n"); // /Name is obsolete - see page 413 in the PDF spec // sb.Append("/Name /"); // sb.Append(_name); //TODO: escape spaces etc. // sb.Append("\r\n"); sb.Append("/BaseFont /"); sb.Append(_underlying.PostScriptName); //TODO: escape spaces etc. sb.Append("\r\n"); // Specify no encoding for "symbolic" fonts if (_underlying.Encoding != null) { sb.Append("/Encoding /"); sb.Append(_underlying.Encoding); sb.Append("\r\n"); } sb.Append("/FontDescriptor "); sb.Append(doc.GetReference(_descriptor).Reference); sb.Append("\r\n"); sb.Append("/FirstChar "); sb.Append(_underlying.FirstChar); sb.Append("\r\n"); sb.Append("/LastChar "); sb.Append(_underlying.LastChar); sb.Append("\r\n"); sb.Append("/Widths "); sb.Append(doc.GetReference(_widths).Reference); sb.Append("\r\n"); sb.Append(">>\r\nendobj\r\n"); Document.WriteData(file, sb.ToString()); _descriptor.Write(file, doc); //_fontFile?.Write(file,generator); in a Type 1 font there is no font file _widths.Write(file, doc, _underlying.UnitsPerEm); // Typically a Type 1 font doesn't need a ToUnicode map because // it uses a standard encoding //_toUnicode.Write(file,generator); }
public void Write(Stream file, Document doc) { ObjectReference thisref = doc.GetReference(this); thisref.ByteOffset = file.Position; ObjectReference realref = doc.GetReference(_realFont); StringBuilder sb = new StringBuilder(); sb.Append(thisref.Id); sb.Append(" obj\r\n<<\r\n"); sb.Append("/Type /Font\r\n"); sb.Append("/Subtype /CIDFontType2\r\n"); sb.Append("/BaseFont /"); sb.Append(_realFont.PostScriptName); sb.Append("\r\n"); sb.Append("/CIDSystemInfo <</Ordering(Identity) /Registry(Adobe) /Supplement 0>>\r\n"); // Use the real font's descriptor ObjectReference descref = doc.GetReference(_realFont.Descriptor); sb.Append("/FontDescriptor "); sb.Append(descref.Reference); sb.Append("\r\n"); sb.Append("/CIDToGIDMap /Identity\r\n"); // If we haven't already got our widths, get them now if (_widths == null) { int count = _realFont.Widths.Count; ushort[] widths = new ushort[count]; for (int x = 0; x < count; ++x) { widths[x] = _realFont.Widths[x]; } _widths = new CIDFontWidths(widths); } // The widths array here is in a special CIDFont format. The data are // the same as on the real font. ObjectReference wref = doc.GetReference(_widths); sb.Append("/W "); sb.Append(wref.Reference); sb.Append("\r\n"); sb.Append(">>\r\nendobj\r\n"); Document.WriteData(file, sb.ToString()); _widths.Write(file, doc, _realFont.UnitsPerEm); }
public void Write(Stream file, ObjectReference pageref, ObjectReference parent, Document doc) { pageref.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(pageref.Id); sb.Append(" obj\r\n"); sb.Append("<<\r\n"); sb.Append("/Type /Page\r\n"); // We have a flat page structure, so the parent is always the catalog sb.Append("/Parent "); sb.Append(parent.Reference); sb.Append("\r\n"); sb.Append("/MediaBox "); sb.Append(_mediaBox.Specification); sb.Append("\r\n"); // Write the string now because we want to write the resources and // content directly to the file Document.WriteData(file, sb.ToString()); sb.Clear(); WriteResources(file, doc); // Construct a content stream and write its reference to the file, // but don't write its contents inside the page dictionary ContentStream stream = new ContentStream(); ObjectReference cref = doc.GetReference(stream); Document.WriteData(file, "/Contents "); Document.WriteData(file, cref.Reference); Document.WriteData(file, "\r\n"); // Close the page object Document.WriteData(file, ">>\r\nendobj\r\n"); // Write the content stream, outside the page dictionary stream.Write(file, cref, _content); // Write the images foreach (Image image in _images) { ObjectReference imageRef = doc.GetReference(image); ObjectReference maskRef = null; if (image.Mask != null) { maskRef = doc.GetReference(image.Mask); } image.Write(file, imageRef, maskRef); } }
public void Write(Stream file) { StringBuilder sb = new StringBuilder(); sb.Append("/ProcSet [ "); foreach (string name in _names) { sb.Append("/"); sb.Append(name); sb.Append(" "); } sb.Append("]\r\n"); Document.WriteData(file, sb.ToString()); }
private void WriteResources(Stream file, Document doc) { Document.WriteData(file, "/Resources\r\n<<\r\n"); _procSet.Write(file); // Font references. The fonts themselves are written directly by the generator. if (_fonts.Fonts.Count > 0) { StringBuilder sb = new StringBuilder(); sb.Append("/Font <<"); foreach (Font font in _fonts.Fonts) { FontReference fontref = new FontReference(doc.GetReference(font)); sb.Append(fontref.AliasReference); sb.Append(" "); TrueTypeFont ttf = font as TrueTypeFont; if (ttf != null) { fontref = new FontReference(doc.GetReference(ttf.RootFont)); sb.Append(fontref.AliasReference); sb.Append(" "); } } sb.Append(">>\r\n"); Document.WriteData(file, sb.ToString()); } // Image references. The images themselves are written elsewhere. if (_images.Count > 0) { StringBuilder sb = new StringBuilder(); sb.Append("/XObject << "); foreach (Image img in _images) { ObjectReference imgRef = doc.GetReference(img); sb.Append("/"); sb.Append(img.Name); sb.Append(" "); sb.Append(imgRef.Reference); sb.Append(" "); } sb.Append(">>\r\n"); Document.WriteData(file, sb.ToString()); } Document.WriteData(file, ">>\r\n"); }
public override void Write(Stream file, Document doc) { ObjectReference fontref = doc.GetReference(this); fontref.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(fontref.Id); sb.Append(" obj\r\n"); sb.Append("<< /Type /Font\r\n"); sb.Append("/Subtype /Type0\r\n"); sb.Append("/BaseFont /"); sb.Append(_descendant.PostScriptName); sb.Append("\r\n"); sb.Append("/Encoding /Identity-H\r\n"); // The Type 0 font has a one-element array of descendant fonts. // The descendant font is a CIDFont (in our case, subtype // CIDFontType2.) The CIDFont points to the same descriptor // as the True Type font. ObjectReference cidref = doc.GetReference(_cidFont); // DescendantFonts is a one-element array, that one entry // being a reference to the descendant font sb.Append("/DescendantFonts [ "); sb.Append(cidref.Reference); sb.Append(" ]\r\n"); ObjectReference uniref = doc.GetReference(_descendant.ToUnicode); sb.Append("/ToUnicode "); sb.Append(uniref.Reference); sb.Append("\r\n"); sb.Append(">>\r\nendobj\r\n"); Document.WriteData(file, sb.ToString()); _cidFont.Write(file, doc); }
public void Write(Stream file, Document doc, ushort unitsPerEm) { ObjectReference wref = doc.GetReference(this); wref.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(wref.Id); sb.Append(" obj\r\n[ "); for (int x = 0; x < _underlying.Count; ++x) { // The raw widths are in font units, but we want thousandths // of a text unit in the dictionary. See page 414. sb.Append(_underlying[x] * 1000 / unitsPerEm); sb.Append(" "); } sb.Append("]\r\nendobj\r\n"); Document.WriteData(file, sb.ToString()); }
public void Write(Stream file, ObjectReference dictRef) { dictRef.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(dictRef.Id); sb.Append(" obj\r\n<<"); foreach (KeyValuePair <string, string> item in _info) { sb.Append("/"); sb.Append(item.Key); sb.Append(" ("); sb.Append(item.Value); sb.Append(")\r\n"); } sb.Append(">>\r\n"); sb.Append("endobj\r\n"); Document.WriteData(file, sb.ToString()); }
public void Write(Stream file, ObjectReference reference, Document doc) { reference.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(reference.Id); sb.Append(" obj\r\n<<\r\n/Type /Catalog\r\n"); ObjectReference pages = doc.GetReference(doc.Pages); sb.Append("/Pages "); sb.Append(pages.Reference); sb.Append("\r\n"); // Dictionary names = new Dictionary(this); // _catalog.AddEntry("/Names",names); // Dictionary metadata = new Dictionary(this); // _catalog.AddEntry("/Metadata",metadata); sb.Append(">>\r\nendobj\r\n"); Document.WriteData(file, sb.ToString()); }
public void Write(Stream file, ObjectReference imageRef, ObjectReference maskRef) { imageRef.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(imageRef.Id); sb.Append(" obj\r\n<<"); sb.Append("/Type /XObject\r\n"); sb.Append("/Subtype /Image\r\n"); sb.Append("/Width "); sb.Append(_size.Width); sb.Append("\r\n"); sb.Append("/Height "); sb.Append(_size.Height); sb.Append("\r\n"); sb.Append("/Length "); sb.Append(_bits.Length); sb.Append("\r\n"); sb.Append("/BitsPerComponent "); sb.Append(_bitsPerPixel); sb.Append("\r\n"); switch (_colorSpace) { case ColorSpace.DeviceRGB: sb.Append("/ColorSpace /DeviceRGB\r\n"); break; case ColorSpace.DeviceGray: sb.Append("/ColorSpace /DeviceGray\r\n"); break; } switch (_filter) { case Filter.DCT: sb.Append("/Filter /DCTDecode\r\n"); break; case Filter.Flate: sb.Append("/Filter /FlateDecode\r\n"); break; } if (maskRef != null) { sb.Append("/SMask "); sb.Append(maskRef.Reference); sb.Append("\r\n"); } sb.Append(">>\r\n"); sb.Append("stream\r\n"); // Write the string now so that we can write the binary data Document.WriteData(file, sb.ToString()); sb.Clear(); file.Write(_bits, 0, _bits.Length); sb.Append("\r\nendstream\r\n"); sb.Append("endobj\r\n"); Document.WriteData(file, sb.ToString()); }
public void Write(Stream file, Document doc) { if (this.Count == 0) { return; } ObjectReference uniref = doc.GetReference(this); uniref.ByteOffset = file.Position; // Prepare the stream so that we can find its length. // The /Length value must be the length of the stream // contents, starting after "stream\r\n" and ending // before "\r\nendstream". StringBuilder sb = new StringBuilder(); sb.Append("/CIDInit /ProcSet findresource\r\n"); sb.Append("begin\r\n"); sb.Append("12 dict\r\n"); sb.Append("begin\r\n"); sb.Append("begincmap\r\n"); sb.Append("/CIDSystemInfo<</Registry(Adobe)/Ordering(UCS)/Supplement 0>>\r\n"); sb.Append("def\r\n"); sb.Append("/CMapName /Adobe-Identity-UCS\r\n"); sb.Append("def\r\n"); sb.Append("/CMapType 2\r\n"); sb.Append("def\r\n"); List <ushort> indices = new List <ushort>(this.Keys); indices.Sort(); sb.Append("1 begincodespacerange\r\n"); sb.Append("<"); sb.Append(Helpers.Hex(indices[0])); sb.Append("><"); sb.Append(Helpers.Hex(indices[indices.Count - 1])); sb.Append(">\r\n"); sb.Append("endcodespacerange\r\n"); // sb.Append("2 beginbfrange\r\n"); // < 0000 >< 005E >< 0020 > // < 005F >< 0061 >[ < 00660066 > < 00660069 > < 00660066006C > ] // sb.Append("endbfrange\r\n"); //TODO: collect the mappings into contiguous ranges and encode //them more efficiently with beginbfrange/endbfrange foreach (ushort glyphIndex in indices) { sb.Append("1 beginbfchar\r\n"); sb.Append("<"); sb.Append(Helpers.Hex(glyphIndex)); sb.Append("><"); sb.Append(Helpers.Hex(this[glyphIndex])); sb.Append(">\r\n"); sb.Append("endbfchar\r\n"); } sb.Append("endcmap\r\n"); sb.Append("CMapName currentdict /CMap defineresource pop\r\n"); sb.Append("end\r\n"); sb.Append("end"); byte[] stream = Encoding.UTF8.GetBytes(sb.ToString()); // Write the stream to the PDF sb.Clear(); sb.Append(uniref.Id); sb.Append(" obj\r\n"); sb.Append("<</Length "); sb.Append(stream.Length); sb.Append(">>\r\n"); sb.Append("stream\r\n"); Document.WriteData(file, sb.ToString()); file.Write(stream, 0, stream.Length); sb.Clear(); sb.Append("\r\nendstream\r\n"); sb.Append("\r\nendobj\r\n"); Document.WriteData(file, sb.ToString()); }
public override void Write(Stream file, Document doc) { // RootFont.Write(file,generator); ObjectReference fontref = doc.GetReference(this); fontref.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(fontref.Id); sb.Append(" obj\r\n"); sb.Append("<< /Type /Font\r\n"); sb.Append("/Subtype /TrueType\r\n"); // /Name is obsolete - see page 413 in the PDF spec // sb.Append("/Name /"); // sb.Append(_name); //TODO: escape spaces etc. // sb.Append("\r\n"); sb.Append("/BaseFont /"); sb.Append(PostScriptName); //TODO: escape spaces etc. sb.Append("\r\n"); // // Specify no encoding for "symbolic" fonts // if(_encoding != null) // { // sb.Append("/Encoding /"); // sb.Append(_encoding); // sb.Append("\r\n"); // } sb.Append("/FontDescriptor "); sb.Append(doc.GetReference(_descriptor).Reference); sb.Append("\r\n"); sb.Append("/FirstChar "); sb.Append(_underlying.FirstCharIndex); sb.Append("\r\n"); sb.Append("/LastChar "); sb.Append(_underlying.LastCharIndex); sb.Append("\r\n"); sb.Append("/Widths "); sb.Append(doc.GetReference(_widths).Reference); sb.Append("\r\n"); sb.Append(">>\r\nendobj\r\n"); Document.WriteData(file, sb.ToString()); _descriptor.Write(file, doc); _fontStream?.Write(file, doc); _widths.Write(file, doc, UnitsPerEm); foreach (KeyValuePair <char, ushort> glyph in _underlying.GlyphIndices) // <char, index> { _toUnicode.Add(glyph.Value, glyph.Key); // <index, char> } _toUnicode.Write(file, doc); }
public void Write(Stream file, Document doc) { ObjectReference descref = doc.GetReference(this); descref.ByteOffset = file.Position; StringBuilder sb = new StringBuilder(); sb.Append(descref.Id); sb.Append(" obj\r\n"); sb.Append("<< /Type /FontDescriptor\r\n"); sb.Append("/FontName /"); sb.Append(_fontName); sb.Append("\r\n"); sb.Append("/Flags "); sb.Append(_flags); sb.Append("\r\n"); sb.Append("/ItalicAngle "); sb.Append(_italicAngle); sb.Append("\r\n"); sb.Append("/Ascent "); sb.Append(_ascent); sb.Append("\r\n"); sb.Append("/Descent "); sb.Append(_descent); sb.Append("\r\n"); sb.Append("/CapHeight "); sb.Append(_capHeight); sb.Append("\r\n"); sb.Append("/AvgWidth "); sb.Append(_avgWidth); sb.Append("\r\n"); sb.Append("/MaxWidth "); sb.Append(_maxWidth); sb.Append("\r\n"); sb.Append("/FontWeight "); sb.Append(_fontWeight); sb.Append("\r\n"); sb.Append("/XHeight "); sb.Append(_xHeight); sb.Append("\r\n"); sb.Append("/StemV "); sb.Append(_stemV); sb.Append("\r\n"); sb.Append("/FontBBox "); sb.Append(_bbox.Specification); sb.Append("\r\n"); if (_fontFile != null) { //TODO: consider compressing the font file sb.Append("/FontFile2 "); sb.Append(doc.GetReference(_fontFile).Reference); sb.Append("\r\n"); } sb.Append(">>\r\nendobj\r\n"); Document.WriteData(file, sb.ToString()); }