MIGRATION GUIDES How to Migrate from Nutrient.io to IronPDF in C# Curtis Chau 發表日期:2026年1月25日 下載 IronPDF NuGet 下載 DLL 下載 Windows 安裝程式 開始免費試用 法學碩士副本 法學碩士副本 將頁面複製為 Markdown 格式,用於 LLMs 在 ChatGPT 中打開 請向 ChatGPT 諮詢此頁面 在雙子座打開 請向 Gemini 詢問此頁面 在 Grok 中打開 向 Grok 詢問此頁面 打開困惑 向 Perplexity 詢問有關此頁面的信息 分享 在 Facebook 上分享 分享到 X(Twitter) 在 LinkedIn 上分享 複製連結 電子郵件文章 從 Nutrient.io(原 PSPDFKit)遷移到 IronPDF 可以簡化您的 .NET PDF 工作流程,因為它將使您從一個採用非同步優先模式的複雜文件智慧平台轉變為專注於 PDF 且具有簡潔同步 API 的程式庫。本指南提供了一個全面的逐步遷移路徑,該路徑消除了平台開銷,同時保留了所有必要的 PDF 功能。 為什麼要從 Nutrient.io 遷移到 IronPDF 平台複雜性問題 Nutrient.io(前身為 PSPDFKit)已從一個 PDF SDK 演變為一個全面的"文件智慧平台"。雖然這種轉變擴展了其功能,但也為那些僅需要可靠 PDF 操作的團隊帶來了重大挑戰: 1.平台過度設計:曾經的 PDF SDK 現在已經發展成為一個完整的文檔智慧平台,具有 AI 功能和文件工作流程功能,但對於簡單的 PDF 任務來說,這些功能可能並不必要。 2.企業定價: Nutrient.io 的目標客戶是大型組織,其定價不透明,需要聯絡銷售部門。 這會對中小型團隊造成障礙,並使預算規劃變得困難。 3.品牌重塑帶來的混亂: PSPDFKit → Nutrient 的轉換導致文件中同時出現兩個名稱,造成文件混亂。軟體包名稱可能仍使用 PSPDFKit,過渡期間的遷移路徑也尚不清楚。 4.非同步優先的複雜性: Nutrient.io 中的所有操作都需要 async/await 模式。 即使是簡單的操作也需要PdfProcessor.CreateAsync()進行初始化,並且基本任務需要非同步方法,這會增加同步工作流程的開銷。 5.依賴項較多:完整平台需要更多資源,軟體包佔用空間較大,初始化時間較長,且需要額外的配置。 Nutrient.io 與 IronPDF 對比 方面 Nutrient.io (PSPDFKit) IronPDF 重點 文檔智慧平台 PDF庫 定價 企業版(聯繫銷售) 透明,出版 建築學 複雜平台 簡單庫 API 風格 非同步優先 使用非同步選項進行同步 依賴關係 重的 輕的 配置 複雜配置對象 簡單明了的屬性 學習曲線 陡峭的(平台) 溫柔(圖書館) 目標用戶 企業 所有團隊規模 對於計劃在 2025 年和 2026 年採用 .NET 10 和 C# 14 的團隊來說,IronPDF 提供了一個更簡單的基礎,可以乾淨利落地集成,而無需完整的文檔智能平台帶來的額外開銷。 開始之前 先決條件 .NET 環境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+ NuGet 存取權限:能夠安裝 NuGet 套件 IronPDF 許可證:請從ironpdf.com取得您的許可證密鑰。 NuGet 套件變更 # Remove Nutrient/PSPDFKit packages dotnet remove package PSPDFKit.NET dotnet remove package PSPDFKit.PDF dotnet remove package Nutrient dotnet remove package Nutrient.PDF # Install IronPDF dotnet add package IronPdf # Remove Nutrient/PSPDFKit packages dotnet remove package PSPDFKit.NET dotnet remove package PSPDFKit.PDF dotnet remove package Nutrient dotnet remove package Nutrient.PDF # Install IronPDF dotnet add package IronPdf SHELL 許可證配置 // Add at application startup (Program.cs or Startup.cs) IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"; // Add at application startup (Program.cs or Startup.cs) IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"; $vbLabelText $csharpLabel 識別 Nutrient.io 使用情況 # Find all Nutrient/PSPDFKit references grep -r "PSPDFKit\|Nutrient\|PdfProcessor\|PdfConfiguration" --include="*.cs" . # Find all Nutrient/PSPDFKit references grep -r "PSPDFKit\|Nutrient\|PdfProcessor\|PdfConfiguration" --include="*.cs" . SHELL 完整 API 參考 初始化映射 Nutrient.io (PSPDFKit) IronPDF 筆記 await PdfProcessor.CreateAsync() new ChromePdfRenderer() 無需異步 processor.Dispose() (自動或手動) 更簡單的生命週期 new PdfConfiguration { ... } renderer.RenderingOptions 基於房產 文件載入映射 Nutrient.io (PSPDFKit) IronPDF 筆記 await processor.OpenAsync(path) PdfDocument.FromFile(path) 預設同步 Document.LoadFromStream(stream) PdfDocument.FromStream(stream) 串流媒體支援 Document.LoadFromBytes(bytes) new PdfDocument(bytes) 位元組數組 PDF產生映射 Nutrient.io (PSPDFKit) IronPDF 筆記 await processor.GeneratePdfFromHtmlStringAsync(html) renderer.RenderHtmlAsPdf(html) 同步方法 await processor.GeneratePdfFromUrlAsync(url) renderer.RenderUrlAsPdf(url) 直接連結 await processor.GeneratePdfFromFileAsync(path) renderer.RenderHtmlFileAsPdf(path) HTML 文件 文檔操作映射 Nutrient.io (PSPDFKit) IronPDF 筆記 await processor.MergeAsync(docs) PdfDocument.Merge(pdfs) 同步 document.PageCount pdf.PageCount 同樣的模式 await document.SaveAsync(path) pdf.SaveAs(path) 同步 document.ToBytes() pdf.BinaryData 位元組數組 註釋和浮水印映射 Nutrient.io (PSPDFKit) IronPDF 筆記 await document.AddAnnotationAsync(index, annotation) pdf.ApplyWatermark(html) 基於HTML new TextAnnotation("text") 浮水印中的 HTML 更靈活 annotation.Opacity = 0.5 CSS opacity: 0.5 CSS樣式 annotation.FontSize = 48 CSS font-size: 48px CSS樣式 程式碼遷移範例 範例 1:HTML 轉 PDF 之前(Nutrient.io): // NuGet: Install-Package PSPDFKit.Dotnet using PSPDFKit.Pdf; using System.Threading.Tasks; class Program { static async Task Main() { var htmlContent = "<html><body><h1>Hello World</h1></body></html>"; using var processor = await PdfProcessor.CreateAsync(); var document = await processor.GeneratePdfFromHtmlStringAsync(htmlContent); await document.SaveAsync("output.pdf"); } } // NuGet: Install-Package PSPDFKit.Dotnet using PSPDFKit.Pdf; using System.Threading.Tasks; class Program { static async Task Main() { var htmlContent = "<html><body><h1>Hello World</h1></body></html>"; using var processor = await PdfProcessor.CreateAsync(); var document = await processor.GeneratePdfFromHtmlStringAsync(htmlContent); await document.SaveAsync("output.pdf"); } } $vbLabelText $csharpLabel (IronPDF 之後): // NuGet: Install-Package IronPdf using IronPdf; class Program { static void Main() { var htmlContent = "<html><body><h1>Hello World</h1></body></html>"; var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf(htmlContent); pdf.SaveAs("output.pdf"); } } // NuGet: Install-Package IronPdf using IronPdf; class Program { static void Main() { var htmlContent = "<html><body><h1>Hello World</h1></body></html>"; var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf(htmlContent); pdf.SaveAs("output.pdf"); } } $vbLabelText $csharpLabel Nutrient.io 的方法需要幾個非同步步驟:使用await PdfProcessor.CreateAsync()建立一個PdfProcessor ,然後呼叫await processor.GeneratePdfFromHtmlStringAsync() ,最後await document.SaveAsync() 。 整個方法必須標記為async Task ,且處理器需要using語句才能正確釋放資源。 IronPDF大大簡化了這個過程。 建立一個ChromePdfRenderer ,呼叫RenderHtmlAsPdf() ,然後使用SaveAs()儲存。 無需 async/await,無需管理處理器生命週期,簡單操作無需using程式碼區塊。 對於不需要在 PDF 工作流程中使用非同步模式的開發人員來說,這種模式更加直覺。 有關其他渲染選項,請參閱HTML 轉 PDF 文件。 範例 2:合併多個 PDF 文件 之前(Nutrient.io): // NuGet: Install-Package PSPDFKit.Dotnet using PSPDFKit.Pdf; using System.Threading.Tasks; using System.Collections.Generic; class Program { static async Task Main() { using var processor = await PdfProcessor.CreateAsync(); var document1 = await processor.OpenAsync("document1.pdf"); var document2 = await processor.OpenAsync("document2.pdf"); var mergedDocument = await processor.MergeAsync(new List<PdfDocument> { document1, document2 }); await mergedDocument.SaveAsync("merged.pdf"); } } // NuGet: Install-Package PSPDFKit.Dotnet using PSPDFKit.Pdf; using System.Threading.Tasks; using System.Collections.Generic; class Program { static async Task Main() { using var processor = await PdfProcessor.CreateAsync(); var document1 = await processor.OpenAsync("document1.pdf"); var document2 = await processor.OpenAsync("document2.pdf"); var mergedDocument = await processor.MergeAsync(new List<PdfDocument> { document1, document2 }); await mergedDocument.SaveAsync("merged.pdf"); } } $vbLabelText $csharpLabel (IronPDF 之後): // NuGet: Install-Package IronPdf using IronPdf; using System.Collections.Generic; class Program { static void Main() { var pdf1 = PdfDocument.FromFile("document1.pdf"); var pdf2 = PdfDocument.FromFile("document2.pdf"); var merged = PdfDocument.Merge(pdf1, pdf2); merged.SaveAs("merged.pdf"); } } // NuGet: Install-Package IronPdf using IronPdf; using System.Collections.Generic; class Program { static void Main() { var pdf1 = PdfDocument.FromFile("document1.pdf"); var pdf2 = PdfDocument.FromFile("document2.pdf"); var merged = PdfDocument.Merge(pdf1, pdf2); merged.SaveAs("merged.pdf"); } } $vbLabelText $csharpLabel Nutrient.io 的合併作業需要使用await PdfProcessor.CreateAsync()建立一個處理器,使用單獨的await processor.OpenAsync()呼叫開啟每個文檔,並建立一個List<PdfDocument>呼叫await processor.MergeAsync()並使用該列表,最後await mergedDocument.SaveAsync() 。 一個基本的合併操作需要五個非同步操作。 IronPDF 將此操作簡化為四行同步程式碼:使用PdfDocument.FromFile()載入每個 PDF,使用靜態PdfDocument.Merge()方法合併,然後儲存。 無需處理器生命週期,無需建立清單(可以直接傳遞文件),也沒有非同步開銷。 了解更多關於合併和拆分PDF的資訊。 範例 3:添加浮水印 之前(Nutrient.io): // NuGet: Install-Package PSPDFKit.Dotnet using PSPDFKit.Pdf; using PSPDFKit.Pdf.Annotation; using System.Threading.Tasks; class Program { static async Task Main() { using var processor = await PdfProcessor.CreateAsync(); var document = await processor.OpenAsync("document.pdf"); for (int i = 0; i < document.PageCount; i++) { var watermark = new TextAnnotation("CONFIDENTIAL") { Opacity = 0.5, FontSize = 48 }; await document.AddAnnotationAsync(i, watermark); } await document.SaveAsync("watermarked.pdf"); } } // NuGet: Install-Package PSPDFKit.Dotnet using PSPDFKit.Pdf; using PSPDFKit.Pdf.Annotation; using System.Threading.Tasks; class Program { static async Task Main() { using var processor = await PdfProcessor.CreateAsync(); var document = await processor.OpenAsync("document.pdf"); for (int i = 0; i < document.PageCount; i++) { var watermark = new TextAnnotation("CONFIDENTIAL") { Opacity = 0.5, FontSize = 48 }; await document.AddAnnotationAsync(i, watermark); } await document.SaveAsync("watermarked.pdf"); } } $vbLabelText $csharpLabel (IronPDF 之後): // NuGet: Install-Package IronPdf using IronPdf; using IronPdf.Editing; class Program { static void Main() { var pdf = PdfDocument.FromFile("document.pdf"); pdf.ApplyWatermark("<h1 style='color:gray;opacity:0.5;'>CONFIDENTIAL</h1>", 50, VerticalAlignment.Middle, HorizontalAlignment.Center); pdf.SaveAs("watermarked.pdf"); } } // NuGet: Install-Package IronPdf using IronPdf; using IronPdf.Editing; class Program { static void Main() { var pdf = PdfDocument.FromFile("document.pdf"); pdf.ApplyWatermark("<h1 style='color:gray;opacity:0.5;'>CONFIDENTIAL</h1>", 50, VerticalAlignment.Middle, HorizontalAlignment.Center); pdf.SaveAs("watermarked.pdf"); } } $vbLabelText $csharpLabel 這個例子突顯了建築結構上的根本差異。 Nutrient.io 使用基於註解的方法:您建立一個TextAnnotation對象,其中包含Opacity和FontSize等屬性,然後遍歷每個頁面,對每個頁面呼叫await document.AddAnnotationAsync(i, watermark) 。 這需要理解註解系統並自行管理循環。 IronPDF 使用基於 HTML 的方法: ApplyWatermark()方法接受帶有 CSS 樣式的 HTML 字串。 水印會在一次呼叫中自動套用於所有頁面。 您可以透過熟悉的 CSS 屬性( color 、 opacity 、 font-size )來控制外觀,而不是透過特定於註解的物件屬性。 這種方法提供了更大的樣式彈性—您可以使用任何 HTML/CSS,包括漸層、圖像和複雜的佈局。 請參閱水印文件以取得更高級的範例。 關鍵遷移說明 異步到同步轉換 最重要的變化是移除不必要的 async/await 模式: // Nutrient.io: Async-first using var processor = await PdfProcessor.CreateAsync(); var document = await processor.GeneratePdfFromHtmlStringAsync(html); await document.SaveAsync("output.pdf"); // IronPDF: 預設同步 (async available when needed) var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf(html); pdf.SaveAs("output.pdf"); // Nutrient.io: Async-first using var processor = await PdfProcessor.CreateAsync(); var document = await processor.GeneratePdfFromHtmlStringAsync(html); await document.SaveAsync("output.pdf"); // IronPDF: 預設同步 (async available when needed) var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf(html); pdf.SaveAs("output.pdf"); $vbLabelText $csharpLabel 如果您確實需要非同步操作,IronPDF 提供了非同步變體,例如RenderHtmlAsPdfAsync() 。 處理器生命週期消除 Nutrient.io 需要建立和處置處理器: // Nutrient.io: Processor lifecycle management using var processor = await PdfProcessor.CreateAsync(); // ... use processor ... // Processor disposed at end of using block // IronPDF: No processor lifecycle var renderer = new ChromePdfRenderer(); // Reuse renderer, no complex lifecycle management // Nutrient.io: Processor lifecycle management using var processor = await PdfProcessor.CreateAsync(); // ... use processor ... // Processor disposed at end of using block // IronPDF: No processor lifecycle var renderer = new ChromePdfRenderer(); // Reuse renderer, no complex lifecycle management $vbLabelText $csharpLabel 配置模式變更 Nutrient.io 使用設定物件; IronPDF 使用以下屬性: // Nutrient.io: Config object var config = new PdfConfiguration { PageSize = PageSize.A4, Margins = new Margins(20, 20, 20, 20) }; var doc = await processor.GeneratePdfFromHtmlStringAsync(html, config); // IronPDF: Properties on RenderingOptions var renderer = new ChromePdfRenderer(); renderer.RenderingOptions.PaperSize = PdfPaperSize.A4; renderer.RenderingOptions.MarginTop = 20; renderer.RenderingOptions.MarginBottom = 20; renderer.RenderingOptions.MarginLeft = 20; renderer.RenderingOptions.MarginRight = 20; var pdf = renderer.RenderHtmlAsPdf(html); // Nutrient.io: Config object var config = new PdfConfiguration { PageSize = PageSize.A4, Margins = new Margins(20, 20, 20, 20) }; var doc = await processor.GeneratePdfFromHtmlStringAsync(html, config); // IronPDF: Properties on RenderingOptions var renderer = new ChromePdfRenderer(); renderer.RenderingOptions.PaperSize = PdfPaperSize.A4; renderer.RenderingOptions.MarginTop = 20; renderer.RenderingOptions.MarginBottom = 20; renderer.RenderingOptions.MarginLeft = 20; renderer.RenderingOptions.MarginRight = 20; var pdf = renderer.RenderHtmlAsPdf(html); $vbLabelText $csharpLabel HTML浮水印註釋 將註解物件替換為 HTML 字串: // Nutrient.io: Annotation object with properties new TextAnnotation("CONFIDENTIAL") { Opacity = 0.5f, FontSize = 48 } // IronPDF: HTML with CSS "<h1 style='opacity:0.5; font-size:48px;'>CONFIDENTIAL</h1>" // Nutrient.io: Annotation object with properties new TextAnnotation("CONFIDENTIAL") { Opacity = 0.5f, FontSize = 48 } // IronPDF: HTML with CSS "<h1 style='opacity:0.5; font-size:48px;'>CONFIDENTIAL</h1>" $vbLabelText $csharpLabel 頁碼處理 Nutrient.io 需要手動統計頁數; IronPDF 內建了佔位符: // Nutrient.io: Manual loop and page counting for (int i = 0; i < doc.PageCount; i++) { var footer = new TextAnnotation($"Page {i + 1} of {doc.PageCount}"); await doc.AddAnnotationAsync(i, footer); } // IronPDF: Built-in placeholders renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter { HtmlFragment = "Page {page} of {total-pages}" }; // Nutrient.io: Manual loop and page counting for (int i = 0; i < doc.PageCount; i++) { var footer = new TextAnnotation($"Page {i + 1} of {doc.PageCount}"); await doc.AddAnnotationAsync(i, footer); } // IronPDF: Built-in placeholders renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter { HtmlFragment = "Page {page} of {total-pages}" }; $vbLabelText $csharpLabel 故障排除 問題 1:未找到 PdfProcessor 問題: IronPDF 中不存在PdfProcessor類別。 解決方案:使用ChromePdfRenderer : // Nutrient.io using var processor = await PdfProcessor.CreateAsync(); // IronPDF var renderer = new ChromePdfRenderer(); // Nutrient.io using var processor = await PdfProcessor.CreateAsync(); // IronPDF var renderer = new ChromePdfRenderer(); $vbLabelText $csharpLabel 問題 2:找不到 GeneratePdfFromHtmlStringAsync 方法 問題:不存在非同步 HTML 方法。 解決方案:使用RenderHtmlAsPdf() : // Nutrient.io var document = await processor.GeneratePdfFromHtmlStringAsync(html); // IronPDF var pdf = renderer.RenderHtmlAsPdf(html); // Nutrient.io var document = await processor.GeneratePdfFromHtmlStringAsync(html); // IronPDF var pdf = renderer.RenderHtmlAsPdf(html); $vbLabelText $csharpLabel 問題 3:未找到文字註釋 問題: IronPDF 中不存在註解類。 解決方案:使用基於 HTML 的浮水印: // Nutrient.io var watermark = new TextAnnotation("DRAFT") { Opacity = 0.5 }; await document.AddAnnotationAsync(0, watermark); // IronPDF pdf.ApplyWatermark("<div style='opacity:0.5;'>DRAFT</div>"); // Nutrient.io var watermark = new TextAnnotation("DRAFT") { Opacity = 0.5 }; await document.AddAnnotationAsync(0, watermark); // IronPDF pdf.ApplyWatermark("<div style='opacity:0.5;'>DRAFT</div>"); $vbLabelText $csharpLabel 問題 4:未找到 MergeAsync 問題:不存在非同步合併方法。 解決方案:使用靜態的PdfDocument.Merge()方法: // Nutrient.io var mergedDocument = await processor.MergeAsync(documentList); // IronPDF var merged = PdfDocument.Merge(pdf1, pdf2); // Nutrient.io var mergedDocument = await processor.MergeAsync(documentList); // IronPDF var merged = PdfDocument.Merge(pdf1, pdf2); $vbLabelText $csharpLabel 遷移清單 遷移前 清點程式碼庫中所有 PSPDFKit/營養素的使用情況 記錄可能需要調整的非同步模式 列出所有配置物件及其屬性 辨識基於標註的特徵(浮水印、標題) 審查表單處理要求 取得 IronPDF 許可證密鑰 軟體包變更 刪除PSPDFKit.NET NuGet 包 刪除Nutrient NuGet 套件 安裝IronPdf NuGet 套件: dotnet add package IronPdf 更新命名空間匯入 程式碼更改 在啟動時新增許可證金鑰配置 將PdfProcessor.CreateAsync()替換為new ChromePdfRenderer() 將processor.GeneratePdfFromHtmlStringAsync()替換為renderer.RenderHtmlAsPdf() 將processor.MergeAsync()替換為PdfDocument.Merge() 將TextAnnotation浮水印轉換為 HTML 浮水印 將配置物件替換為RenderingOptions屬性 更新頁首/頁尾,使用有佔位符的HtmlHeaderFooter元件 刪除不必要的 async/await 模式 移民後 移除不再需要的 async/await 執行迴歸測試,比較 PDF 輸出 核對頁首/頁尾的頁碼 測試浮水印渲染 更新 CI/CD 管線 Curtis Chau 立即與工程團隊聊天 技術撰稿人 Curtis Chau 擁有電腦科學學士學位(卡爾頓大學),專長於前端開發,精通 Node.js、TypeScript、JavaScript 和 React。Curtis 對製作直覺且美觀的使用者介面充滿熱情,他喜歡使用現代化的架構,並製作結構良好且視覺上吸引人的手冊。除了開發之外,Curtis 對物聯網 (IoT) 也有濃厚的興趣,他喜歡探索整合硬體與軟體的創新方式。在空閒時間,他喜歡玩遊戲和建立 Discord bots,將他對技術的熱愛與創意結合。 相關文章 發表日期 2026年2月1日 How to Migrate from ZetPDF to IronPDF in C# Master the migration from ZetPDF to IronPDF with this complete C# guide. Switch from a coordinate-based library to a modern HTML-to-PDF solution. Includes code examples for HTML conversion, merging PDFs, and removing PDFSharp dependencies. 閱讀更多 發表日期 2026年2月1日 How to Migrate from Scryber.Core to IronPDF in C# Master the migration from Scryber.Core to IronPDF with this complete C# guide. Switch from custom XML/HTML parsing to a modern Chromium renderer. Includes code examples for HTML conversion, URL rendering, and replacing proprietary bindings. 閱讀更多 發表日期 2026年2月1日 How to Migrate from XFINIUM.PDF to IronPDF in C# Master the migration from XFINIUM.PDF to IronPDF with this complete C# guide. Switch from manual coordinate-based positioning to declarative HTML/CSS rendering. Includes code examples for replacing graphics primitives and automatic layout. 閱讀更多 How to Migrate from PDFBolt to IronPDF in C#How to Migrate from NReco PDF Gener...
發表日期 2026年2月1日 How to Migrate from ZetPDF to IronPDF in C# Master the migration from ZetPDF to IronPDF with this complete C# guide. Switch from a coordinate-based library to a modern HTML-to-PDF solution. Includes code examples for HTML conversion, merging PDFs, and removing PDFSharp dependencies. 閱讀更多
發表日期 2026年2月1日 How to Migrate from Scryber.Core to IronPDF in C# Master the migration from Scryber.Core to IronPDF with this complete C# guide. Switch from custom XML/HTML parsing to a modern Chromium renderer. Includes code examples for HTML conversion, URL rendering, and replacing proprietary bindings. 閱讀更多
發表日期 2026年2月1日 How to Migrate from XFINIUM.PDF to IronPDF in C# Master the migration from XFINIUM.PDF to IronPDF with this complete C# guide. Switch from manual coordinate-based positioning to declarative HTML/CSS rendering. Includes code examples for replacing graphics primitives and automatic layout. 閱讀更多