在用uwp生成pdf的时候,发展此类类库有限,有的也需要钱,我最后实现pdf的底层方法生成pdf,代码如下
private async void GeneratePdf() { var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("uwpCSharp.pdf", Windows.Storage.CreationCollisionOption.ReplaceExisting); using (var stream = await System.IO.WindowsRuntimeStorageExtensions.OpenStreamForWriteAsync(file)) { using (var writer = new System.IO.StreamWriter(stream, System.Text.Encoding.UTF8)) { List<long> xrefs = new List<long>(); writer.WriteLine("%PDF-1.2"); writer.Write("%"); writer.Flush(); byte[] bytes = { 0, 0, 0, 0 }; stream.Write(bytes, 0, 4); stream.Flush(); writer.WriteLine(""); writer.Flush(); stream.Flush(); xrefs.Add(stream.Position); writer.WriteLine("1 0 obj"); writer.WriteLine("<<"); writer.WriteLine(" /Type /Catalog"); writer.WriteLine(" /Pages 2 0 R"); writer.WriteLine(">>"); writer.WriteLine("endobj"); // #2: 页面列表 - 我们只有一页文字 writer.Flush(); stream.Flush(); xrefs.Add(stream.Position); writer.WriteLine("2 0 obj"); writer.WriteLine("<<"); writer.WriteLine(" /Type /Pages"); writer.WriteLine(" /Kids [3 0 R]"); writer.WriteLine(" /Count 1"); writer.WriteLine(">>"); writer.WriteLine("endobj"); // #3: 页面 - 这里放文字、资源等 writer.Flush(); stream.Flush(); xrefs.Add(stream.Position); writer.WriteLine("3 0 obj"); writer.WriteLine("<<"); writer.WriteLine(" /Type /Page"); writer.WriteLine(" /Parent 2 0 R"); writer.WriteLine(" /MediaBox [0 0 612 792]"); // 默认的用户空间: 72/inch writer.WriteLine(" /Resources"); writer.WriteLine(" <<"); writer.WriteLine(" /ProcSet [/PDF/Text]"); // 这个pdf只有文本 writer.WriteLine(" /Font"); writer.WriteLine(" <<"); writer.WriteLine(" /F0 4 0 R"); // 定义的三种字体, #4, #5 和 #6 writer.WriteLine(" /F1 5 0 R"); writer.WriteLine(" /F2 6 0 R"); writer.WriteLine(" >>"); writer.WriteLine(" >>"); writer.WriteLine(" /Contents 7 0 R"); writer.WriteLine(">>"); writer.WriteLine("endobj"); // #4, #5, #6: 三钟字体,我们使用pdf默认字体 //使用WinAnsi字符编码,定义如下 writer.Flush(); stream.Flush(); xrefs.Add(stream.Position); writer.WriteLine("4 0 obj"); writer.WriteLine("<<"); writer.WriteLine(" /Type /Font"); writer.WriteLine(" /Subtype /Type1"); writer.WriteLine(" /Encoding /WinAnsiEncoding"); writer.WriteLine(" /BaseFont /Times-Roman"); writer.WriteLine(">>"); writer.Flush(); stream.Flush(); xrefs.Add(stream.Position); writer.WriteLine("5 0 obj"); writer.WriteLine("<<"); writer.WriteLine(" /Type /Font"); writer.WriteLine(" /Subtype /Type1"); writer.WriteLine(" /Encoding /WinAnsiEncoding"); writer.WriteLine(" /BaseFont /Times-Bold"); writer.WriteLine(">>"); writer.Flush(); stream.Flush(); xrefs.Add(stream.Position); writer.WriteLine("6 0 obj"); writer.WriteLine("<<"); writer.WriteLine(" /Type /Font"); writer.WriteLine(" /Subtype /Type1"); writer.WriteLine(" /Encoding /WinAnsiEncoding"); writer.WriteLine(" /BaseFont /Times-Italic"); writer.WriteLine(">>"); // #7:内容页面。这是用postscript编写的, // 有兴趣的朋友可以查看PDF 1.2参考手册第8章 writer.Flush(); stream.Flush(); xrefs.Add(stream.Position); System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.AppendLine("BT"); // BT =开始文本对象 sb.AppendLine("/F0 30 Tf"); // Tf = 使用文字 "F0" 定义文字大小为 "30" sb.AppendLine("30 TL"); // TL = 设置高度为 "30" sb.AppendLine("140.0 780.0 Td"); // Td = 文本坐标的位置 "140.0", "780.0" sb.AppendLine("1.0 0.0 0.6 rg"); // rg = 字体前景颜色设置 sb.AppendLine("(Microsoft Corporation India) ‘"); sb.AppendLine("ET"); //画线 //顶部的线 sb.AppendLine("BT"); sb.AppendLine("10 TL"); sb.AppendLine("50.0 730.0 Td"); sb.AppendLine("0.0 0.0 0.0 rg"); sb.AppendLine("(__________________________________)‘"); sb.AppendLine("ET"); //左边 sb.AppendLine("BT"); sb.AppendLine("10 TL"); sb.AppendLine("47.0 703.0 Td"); sb.AppendLine("0.0 0.0 0.0 rg"); for (int i = 0; i <= 60; i++) { sb.AppendLine("(|)‘"); } sb.AppendLine("ET"); //中间的线 sb.AppendLine("BT"); sb.AppendLine("10 TL"); sb.AppendLine("240.0 703.0 Td"); sb.AppendLine("0.0 0.0 0.0 rg"); for (int i = 0; i <= 60; i++) { sb.AppendLine("(|)‘"); } sb.AppendLine("ET"); //画右边的线 sb.AppendLine("BT"); sb.AppendLine("10 TL"); sb.AppendLine("557.0 703.0 Td"); sb.AppendLine("0.0 0.0 0.0 rg"); for (int i = 0; i <= 60; i++) { sb.AppendLine("(|)‘"); } sb.AppendLine("ET"); //底部的线 sb.AppendLine("BT"); sb.AppendLine("10 TL"); sb.AppendLine("50.0 102.0 Td"); sb.AppendLine("0.0 0.0 0.0 rg"); sb.AppendLine("(__________________________________)‘"); sb.AppendLine("ET"); //文字 sb.AppendLine("BT"); sb.AppendLine("/F0 15 Tf"); sb.AppendLine("20 TL"); sb.AppendLine("70.0 670.0 Td"); sb.AppendLine("0.0 0.2 1.0 rg"); sb.AppendLine("(Parameter1)‘"); sb.AppendLine("ET"); // sb.AppendLine("BT"); sb.AppendLine("/F0 15 Tf"); sb.AppendLine("20 TL"); sb.AppendLine("0.0 0.0 0.0 rg"); sb.AppendLine("260.0 670.0 Td"); sb.AppendLine("(test1) ‘"); sb.AppendLine("ET"); // sb.AppendLine("BT"); sb.AppendLine("/F0 15 Tf"); sb.AppendLine("20 TL"); sb.AppendLine("0.0 0.2 1.0 rg"); sb.AppendLine("70.0 645.0 Td"); sb.AppendLine("(Parameter2)‘"); sb.AppendLine("ET"); // sb.AppendLine("BT"); sb.AppendLine("/F0 15 Tf"); sb.AppendLine("20 TL"); sb.AppendLine("0.0 0.0 0.0 rg"); sb.AppendLine("260.0 645.0 Td"); sb.AppendLine("(test2) ‘"); sb.AppendLine("ET"); // sb.AppendLine("BT"); sb.AppendLine("/F0 15 Tf"); sb.AppendLine("20 TL"); sb.AppendLine("0.0 0.2 1.0 rg"); sb.AppendLine("70.0 615.0 Td"); sb.AppendLine("(Parameter3)‘"); sb.AppendLine("ET"); // sb.AppendLine("BT"); sb.AppendLine("/F0 15 Tf"); sb.AppendLine("20 TL"); sb.AppendLine("260.0 615.0 Td"); sb.AppendLine("0.0 0.0 0.0 rg"); sb.AppendLine("(test3) ‘"); // // sb.AppendLine("BT"); sb.AppendLine("/F0 15 Tf"); sb.AppendLine("20 TL"); sb.AppendLine("0.0 0.2 1.0 rg"); sb.AppendLine("70.0 575.0 Td"); sb.AppendLine("(Parameter4)‘"); sb.AppendLine("ET"); // sb.AppendLine("BT"); sb.AppendLine("/F0 15 Tf"); sb.AppendLine("20 TL"); sb.AppendLine("260.0 575.0 Td"); sb.AppendLine("0.0 0.0 0.0 rg"); sb.AppendLine("(test4) ‘"); sb.AppendLine("ET"); // writer.WriteLine("7 0 obj"); writer.WriteLine("<<"); writer.WriteLine(" /Length " + sb.Length); writer.WriteLine(">>"); writer.WriteLine("stream"); writer.Write(sb.ToString()); writer.WriteLine(" q"); writer.WriteLine(" 156 0 0 272 100 200 cm"); //[1 2 3 4 5 6 cm] translate to (5,6) and scale for 1 writer.WriteLine(" /Img1 Do"); writer.WriteLine(" Q"); writer.WriteLine("endstream"); writer.WriteLine("endobj"); writer.Flush(); stream.Flush(); dynamic xref_pos = stream.Position; writer.WriteLine("xref"); writer.WriteLine("1 " + xrefs.Count); long xref = 0; foreach (long xref_loopVariable in xrefs) { xref = xref_loopVariable; writer.WriteLine("{0:0000000000} {1:00000} n", xref, 0); } // PDF-TRAILER. PDF以这个节点结尾. writer.WriteLine("trailer"); writer.WriteLine("<<"); writer.WriteLine(" /Size " + xrefs.Count); writer.WriteLine(" /Root 1 0 R"); writer.WriteLine(">>"); writer.WriteLine("startxref"); writer.WriteLine(xref_pos); writer.WriteLine("%%EOF"); } } await Windows.System.Launcher.LaunchFileAsync(file); }