u/jhaygood86

Drawing & Text Shaping -- all open source, cross platform, and AOT compatible

Have you ever needed to draw into a canvas and export that into PNG, JPG, WebP, or AVIF?

How about paint some properly shaped text into that image?

There's several options on the market today, but they are all either commercial paid offerings or are wrappers around native libraries and thus have deployment complications and don't run everywhere .NET does

Well, as some of you know, I'm the maintainer of PeachPDF (https://peachpdf.net/), an open source HTML to PDF rendering engine. Today, I'm not talking about that, though 0.9.21 did land today. Well, any HTML layout engine needs to draw shapes and layout text, most of the work is determining what to paint and where, and then actually painting it into a canvas, and for text, it also needs to know exactly what glyph to put where, and for rasterized text (rare for a PDF admittedly), whether or not to hint the text.

Well, PeachPDF gained some new .NET dependencies this week, though it's mostly just PeachPDF code being liberated from only ever serving PeachPDF! Those dependencies are the PeachDrawing suite of libraries:

  • PeachDrawing.Text: This is your font, text shaping, and hinting engine. This loads OpenType, TrueType, CFF, WOFF, and WOFF2 fonts, shapes some text using those fonts, and tells you which glyph to place and where. You can extract text outlines, you can subset a font, and it has some convenience helpers for things like laying out a whole paragraph.
  • PeachDrawing.Core: Core Canvas abstractions, including integration with PeachDrawing.Text. This is what you would use if you wanted to build your own canvas abstraction, and it's what PeachPDF uses to build a PDF-backed canvas
  • PeachDrawing: A raster canvas implementation with PeachImage integration, so you can export to any PeachImage supported format.

These libraries are maintained and versioned alongside PeachPDF, but are designed to be used outside of PeachPDF. If there are API gaps, or you want to contribute, contributions or suggestions or bugfixes are welcome. The current API surface is what an HTML layout engine needs, which admittedly is a lot, but is far from complete or the best.

If you are currently using SkiaSharp and wished you had something pure managed and AOT-compatible, this is likely a good replacement. Alternatively, if using ImageSharp or SixLabors.Fonts, and you don't qualify for using it under the broadly available Apache 2.0 license grants available, and you are unable or unwilling to license it commercially, this should cover at least some of your needs. If there's a gap, I'd love to hear about it! Most of the API surface exists to be able to render various CSS and SVG constructs, so there are likely gaps in available features.

All of these libraries are currently pre-1.0, but the goal is to release 1.0 in early 2027.

They are all BSD 3-clause licensed. They are free and open source forever. They do include MIT and BSD-licensed third party code that was bundled into PeachPDF before.

You can find them on GitHub in the PeachPDF repo (https://github.com/jhaygood86/PeachPDF), they are live on NuGet, and there's documentation online on the PeachPDF website.

reddit.com
u/jhaygood86 — 13 days ago

An Amazing Week in PeachPDF

I had a huge influx of issues and pull requests from a handful of new contributors, almost 100 pull requests total, and this week's release of PeachPDF has a lot of major improvements as a result:

  1. Allocation is down 79% in our test corpus, with some individual files having 96% less allocations.
  2. Wall-clock rendering time is down 37% across the corpus, with some files rendering over 300% faster

It also has major spec compliance updates with tables, per-page rules, flexbox and grid updates, text shaping and font lookup, including emoji and color glyphs seeing updates, including the ability to copy and paste them from the PDF, as well as just general fixes across the pipeline.

If you currently have HTML with modern CSS and SVG, and you want it in PDF, and you use .NET 8 or better, PeachPDF is likely your very best choice for rendering it. (Note: we do not support JavaScript, so if that's you, look at some of the Chromium using competition, and I apologize for the headaches you'll have)

  • Most of the modern standards are supported, including the vast majority of all of the generated content and print-specific CSS features. It even supports PDF/A now!
  • Runs basically everywhere .NET does. It likely even works on your watch. There are known users on Android, iOS, macOS, Linux, Windows, and our demo website runs in Blazor WASM. There are some gaps on iOS (around fonts) and WASM (around support for Brotli) that limits specific features, but for the most part, it just works everywhere.
  • It's small, only 3.7 MB on .NET 10. Including ALL of the dependencies, it's under 12 MB total, and almost all of that is BouncyCastle.Cryptography.dll which is a dependency of MimeKit, which is used for HTML parsing and MHTML support

This is the only 100% open source (BSD licensed) HTML to PDF library for .NET that is 100% pure managed .NET. No native libraries, no Chromium instances or outdated WebKit ports, no shelling out to a executable, no hoping it works on your deployment target, no fuss working on containers or serverless environments.

So... how does it work underneath the covers?

  1. We parse HTML using MimeKit's HtmlTokenizer, which produces a stream of tag and data tokens
  2. This gets converted into a DOM like structure, with each tag or text element represented as a CssBox
  3. We normalize the DOM structure according to HTML and CSS rules, and extract the stylesheets. Those get parsed using a heavily modified in-library fork of ExCSS into a Stylesheet object which contains a strongly typed collection of rules
  4. We then cascade those rules onto the CssBox's above using a source-generated layer which translates the properties from the style rules into typed properties on each box. After cascade, we perform various corrections to the now-cascaded DOM-like tree according to the CSS specs
  5. Layout is performed on the tree which calculates the page, position and size of every CssBox and builds a fragment tree from it. This also includes creating line boxes which then have their text shaped and measured, loading external image resources, etc.., since all of that is needed to calculate where each box goes. This includes all of the special layout engines such as tables, flexbox, gird, multi-column support, and SVG, and all of the fragmentation features such as page and column breaking, and which content stays on one page or gets moved to the next page.
  6. Painting takes the fragment tree and then builds PDF pages out of each top-level fragment (which is 1:1 to a page). This is where we tell the PDF engine where to put each string, where to draw lines and rectangles, images, paths, polygons, and what brushes and pens to use and when. Both HTML and SVG go throguh this layer, so they are natively rendered into the PDF as vector graphics. The text painting also detects emojis and converts those to vectors directly as well through the same engine. The PDF engine we use is a highly modified, stripped down, optimized in-library fork of PdfSharpCore, which is itself a fork of PDFsharp.
  7. From there, the PDF pages are constructed into a PDF document using the PDF engine which we then write to the stream provided by the caller.

The overall steps are basically the same steps any web browser does, but A) we do it entirely in C#, and B) our render target is natively PDF

This library was forked from HTML-Renderer almost a decade ago, from ExCSS about 2 years ago, and PdfSharpCore around 8 years ago. We are in-progress in upstreaming some of the ExCSS and HTML-Renderer improvements, but that will take some time (though ExCSS 4.3.2 has quite a bit of our changes already in it)

reddit.com
u/jhaygood86 — 1 month ago

Updates in the world of the Peach suite of open source libraries!

I maintain 2 open source libraries for .NET that solve real issues:

PeachPDF (which has been around a while) and PeachImage (which is brand new!)

My goal with these libraries has always been to build permissively licensed (MIT or BSD) libraries that do their jobs really well where the alternatives have real world drawbacks, either in terms of licensing or packaging

PeachPDF

https://peachpdf.net/ and https://github.com/jhaygood86/PeachPDF

PeachPDF is my pure .NET HTML to PDF library. It doesn't use a headless browser to operate, or a native command line tool. It runs essentially everywhere .NET does from WASM to mobile to serverless functions, and HTML+SVG+CSS is the design language. The alternatives are all have drawbacks in some way or another. It's also BSD 3-clause licensed and will remain so forever.

PeachPDF's core was forked from HTML-Renderer a decade ago and has seen major upgrades. You can kind of recognize some of the code in the class names, but the implementations have long since diverged, though there's some ongoing work to minimize that.

On top of that HTML core, we've replaced HTML parsing with MimeKit's HTML tokenizer and CSS parsing with a vendored version of ExCSS. On the PDF side, we used a vendored version of PdfSharpCore that has been highly customized for the purposes of laying out HTML+CSS+SVG. It can do things that PDFsharp cannot do, so we have no plans on switching to upstream PDFsharp. Both vendored libraries have seen extensive customization, though most (but not all) of the ExCSS changes have been submitted to ExCSS. I'll keep contributing PRs there regularly.

CSS support is quite good these days, though there are gaps and edge cases, as well as bugs. We have a test suite of almost 9,000 tests guaranteeing that once we fix an issue, it stays fixed. We support .NET 8+ (and we multi-target .NET 10), and the plan is to support every supported .NET version that Microsoft does, so we can take advantage of the latest features

PeachImage

https://github.com/jhaygood86/PeachImage

PeachImage is a pure .NET image decoding / encoding library. It doesn't use native decoders and will always be MIT licensed.

PeachImage is new. PeachPDF originally used ImageSharp for image loading, which worked great, but ImageSharp's licensing changes have been painful, and scared away users even though they could use it transitvely just fine under the dual source license scheme of ImageSharp.

So, I switched to StbImageSharp, which worked great, but didn't support modern image formats. SkiaSharp is essentially a wrapper around Skia which uses common open source image format libraries, and thus has native packaging issues.

So, PeachImage was born. With the rise of AI-assisted development, and a wide test corpus sourced from the native libraries, applications that want to be able to decode and encode popular image formats without native libraries or commercial license fees now can do so.

It's not (and will probably never be) as **fast** as SkiaSharp, but its faster than StbImageSharp in many cases. No idea how it compares to ImageSharp, but hey, its MIT licensed, and it runs everywhere .NET 10 does. And, there are cases its faster than SkiaSharp even (BMP for instance, which is needed for PDF, and SkiaSharp doesn't even support BMP-encoding, as well as some PNG images). It's generally 1-2x slower than SkiaSharp, so it won't be drastically slower in most workloads. It takes advantage of modern .NET features, including vectorization and platform-specific intrinsics, to improve decoding and encoding performance, as well as reducing memory allocations.

It currently supports BMP, JPEG, PNG, GIF, and WebP, with AVIF coming soon. There's some gaps in specific features (i.e., WebP encoding isn't there yet, and WebP animations aren't supported yet), but those are features that are on the roadmap.

This library is not, and is not intended to be, a replacement for ImageSharp or SkiaSharp for **drawing**. This just deals with encoding and decoding images.

reddit.com
u/jhaygood86 — 2 months ago
▲ 0 r/dotnet

Join the PeachTrace Limited Beta

There are quite a few expensive options for observability with DataDog being the 800-lb Gorilla. They all cost an arm or a leg, generally are behind a vendor cloud or use expensive (infrastructure or software) on prem software to work and require entire teams to manage.

After having sticker shock at DataDog bills, I decided to build my own simpler alternative built on OpenTelemetry that has the parts that work for software developer teams. This will not be an open source project, but a product I plan on monetizing at a significant cost savings over DataDog for small teams who don't need a $50,000 annual DataDog contract

The product is still under active development, but it's ready for teams to test it out and see what the limits are and what the missing gaps are.

What's there today?

- Metric storage and querying

- Log storage, searching, filtering, including some special views such as contextual logging

- Distributed traces including surfacing events and logs that happened in the trace

- Query Performance

- Error Tracking

- Full API

- MCP Server -- I use this heavily as a dogfood.

- Local and Entra authentication

It all runs on the infrastructure you probably have today, using Docker and SQL Server 2025 (including the Express Edition). If there's interest in a Windows installer, might do that as well.

It's all built in .NET 10 on the backend and Angular 22 on the frontend. It supports any application capable of emitting OpenTelemetry metrics with bearer token authentication using OTLP via HTTP and gRPC. There's special support in the error tracking module for C#, Node.js, Python, Java, and Go since it requires parsing stack traces. Other languages are easy to add support for if there's demand.

There's no phoning home either except for an optional automatic license key refresh module that can be turned off.

Take a look online at https://peachtrace.com/, and if interested, reach out and we can get you set up.

u/jhaygood86 — 2 months ago
▲ 132 r/dotnet

An update on the world of PeachPDF

PeachPDF is the HTML -> PDF engine I've been building for the last decade that renders HTML into PDF without using a headless browser or external process.

We target .NET 8+, but we also multi-target .NET 10+. We support everywhere .NET 8+ runs, though some features don't work on certain platforms. As an example, iOS doesn't expose system fonts directly as font files, so you have to register fonts directly.

Some updates:

We launched a website: https://peachpdf.net/ This has all of the documentation you'd ever need

I also added a lot of new features:

  1. SVG support -- we already have a very good graphics abstraction, so SVG support is essentially just building a scene graph and rendering it, with some basic integration with the other parts of the stack (CSS Cascade, layout inside HTML)

  2. CSS Grid support

  3. Lots of CSS parsing updates, such as nested CSS, @layer support, CSS Properties, @media evaluation and correctness fixes

  4. New CSS layout and painting features: clip-path, aspect-ratio, object-fit

  5. CSS Color updates

  6. Improved font support: we now use runes for lookup, and we use CSS unicode-range for matching, and we added support for monochrome and color emojis. For features not natively supported by PDF, we can extract the glyph outlines from the font and paint the text as vectors. This was needed for color emojis and several SVG text features

  7. More paged media improvements

  8. A new .NET AOT command line tool that wraps PeachPDF for use where the .NET library doesn't make sense. Future plans include exposing PeachPDF as a C library so that it can be used from Node.js and Python as well.

As a side project, I've also been working on back porting improvements to the upstream projects that I depend on, such as ExCSS and HTML-Renderer. ExCSS just released a new version that is almost all backports from PeachPDF, and the first 2 foundational features have outstanding PRs waiting approval to HTML-Renderer

And to answer a question -- there is significant use of AI for spec conformance features. It's a great use of AI, since it can read a specification and identity gaps. All of the non-mechanical work is done by myself. Considering I started writing this 10 years ago, it's not a vibe coded project since that didn't even exist when I started.

reddit.com
u/jhaygood86 — 3 months ago
▲ 66 r/dotnet

PeachPDF -- Fully Managed HTML to PDF Conversion

PeachPDF is a pure .NET HTML -> PDF rendering library, with a recently released 0.9 release. What does pure .NET mean? This means no Chromium wrappers, no out-of-process tools, no managed libraries, and no limitations of where it will run.

tl;dr -- if you need HTML to PDF conversion, check us out at https://peachpdf.net/

If .NET 8 runs somewhere, so will this. And as a side benefit, all of the performance improvements made in .NET benefit this library immediately.

In the last year, we've made great strides with standards and features support, such as page-level header and footers use CSS Paged Media and CSS Generated Content support.

The list of what's NOT supported is probably the most relevant list:

  • SVG -- we plan on implementing it though
  • CSS Flex (coming in 0.9.1)
  • CSS Grid (coming in 0.9.2)
  • CSS Transforms (coming in 0.9.1 except for perspective)
  • CSSTransitions & Animations (its a PDF, no plans on supporting it)
  • CSS Filters & Effects
  • CSS Variables (coming in 0.9.1)
  • CSS calc() expressions (coming in 0.9.1)
  • CSS Psuedo-classes and psuedo-elements still only have partial support
  • Editable Forms
  • Tagged PDFs
  • PDF/A

The 3 main competitors to this are PuppeteerSharp, IronPDF, and PrinceXML. All have their drawbacks, mostly in terms of having to ship native code for all of them (Chromium for the first 2, Prince's native executive for PrinceXML)

PuppeteerSharp and IronPDF are pixel perfect, but... your shipping a huge browser engine. PrinceXML is a lot closer to how PeachPDF works, but its still a separate native executable.

If you've ever tried running these in Azure Functions, Docker, AWS Lambda, or inside Android or iOS, you know how much a PITA it is (if it's even possible). PeachPDF? It just works in all of these places, because its 100% C#

And performance? It's essentially instant for most normal-sized documents using pretty minimal amounts of memory. I haven't formally benchmarked it yet (I will at some point soon), but the peak memory usage is going to be early in the rendering pipeline while the CSS tree is applied to the DOM tree parsed from HTML. Layout is one of the most significant CPU-intensive portions, but its essentially just calculating X, Y, Width, and Height for every DOM element, so its not excessively expensive.

The best part? This is all 100% free and open source at https://github.com/jhaygood86/PeachPDF

reddit.com
u/jhaygood86 — 3 months ago