{"id":17858368,"url":"https://github.com/linebender/tiny-skia","last_synced_at":"2025-12-12T15:41:53.502Z","repository":{"id":37590463,"uuid":"288731115","full_name":"linebender/tiny-skia","owner":"linebender","description":"A tiny Skia subset ported to Rust","archived":false,"fork":false,"pushed_at":"2025-08-28T17:00:48.000Z","size":1240,"stargazers_count":1410,"open_issues_count":37,"forks_count":81,"subscribers_count":28,"default_branch":"main","last_synced_at":"2025-10-19T11:52:39.858Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/linebender.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-19T12:51:42.000Z","updated_at":"2025-10-19T02:00:17.000Z","dependencies_parsed_at":"2024-03-06T18:16:02.569Z","dependency_job_id":"71187f76-52d8-4fd0-a425-e6b823f0ebed","html_url":"https://github.com/linebender/tiny-skia","commit_stats":{"total_commits":236,"total_committers":10,"mean_commits":23.6,"dds":0.05932203389830504,"last_synced_commit":"00d477829fd66853dcb853e60808b8b435197da2"},"previous_names":["linebender/tiny-skia","razrfalcon/tiny-skia"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/linebender/tiny-skia","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linebender%2Ftiny-skia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linebender%2Ftiny-skia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linebender%2Ftiny-skia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linebender%2Ftiny-skia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/linebender","download_url":"https://codeload.github.com/linebender/tiny-skia/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linebender%2Ftiny-skia/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27685630,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-12T02:00:06.775Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-28T05:01:16.364Z","updated_at":"2025-12-12T15:41:53.482Z","avatar_url":"https://github.com/linebender.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# tiny-skia\n![Build Status](https://github.com/linebender/tiny-skia/workflows/Rust/badge.svg)\n[![Crates.io](https://img.shields.io/crates/v/tiny-skia.svg)](https://crates.io/crates/tiny-skia)\n[![Documentation](https://docs.rs/tiny-skia/badge.svg)](https://docs.rs/tiny-skia)\n\n`tiny-skia` is a tiny [Skia] subset ported to Rust.\n\nThe goal is to provide an absolute minimal, CPU only, 2D rendering library for the Rust ecosystem,\nwith a focus on a rendering quality, speed and binary size.\n\nAnd while `tiny-skia` is definitely tiny, it support all the common 2D operations\nlike: filling and stroking a shape with a solid color, gradient or pattern;\nstroke dashing; clipping; images blending; PNG load/save.\nThe main missing feature is text rendering\n(see [#1](https://github.com/linebender/tiny-skia/issues/1)).\n\n**Note:** this is not a Skia replacement and never will be. It's more of a research project.\n\nMSRV: stable\n\n## Motivation\n\nThe main motivation behind this library is to have a small, high-quality 2D rendering\nlibrary that can be used by [resvg]. And the choice is rather limited.\nYou basically have to choose between [cairo], Qt and Skia. And all of them are\nrelatively bloated, hard to compile and distribute. Not to mention that none of them\nare written in Rust.\n\nBut if we ignore those problems and focus only on quality and speed alone,\nSkia is by far the best one.\nHowever, the main problem with Skia is that it's huge. Really huge.\nIt supports CPU and GPU rendering, multiple input and output formats (including SVG and PDF),\nvarious filters, color spaces, color types and text rendering.\nIt consists of 370 KLOC without dependencies (around 7 MLOC with dependencies)\nand requires around 4-8 GiB of disk space to be built from sources.\nAnd the final binary is 3-8 MiB big, depending on enabled features.\nNot to mention that it requires `clang` and no other compiler\nand uses an obscure build system (`gn`) which was using Python2 until recently.\n\n`tiny-skia` tries to be small, simple and easy to build.\nCurrently, it has around 14 KLOC, compiles in less than 5s on a modern CPU\nand adds around 200KiB to your binary.\n\n## Performance\n\nCurrently, `tiny-skia` is 20-100% slower than Skia on x86-64 and about 100-300% slower on ARM.\nWhich is still faster than [cairo] and [raqote] in many cases.\nSee benchmark results [here](https://linebender.github.io/tiny-skia/x86_64.html).\n\nThe heart of Skia's CPU rendering is\n[SkRasterPipeline](https://github.com/google/skia/blob/master/src/opts/SkRasterPipeline_opts.h).\nAnd this is an extremely optimized piece of code.\nBut to be a bit pedantic, it's not really a C++ code. It relies on clang's\nnon-standard vector extensions, which means that it works only with clang.\nYou can actually build it with gcc/msvc, but it will simply ignore all the optimizations\nand become 15-30 *times* slower! Which makes it kinda useless.\n\nAlso note, that neither Skia or `tiny-skia` are supporting dynamic CPU detection,\nso by enabling newer instructions you're making the resulting binary non-portable.\n\nEssentially, you will get a decent performance on x86 targets by default.\nBut if you are looking for an even better performance, you should compile your application\nwith `RUSTFLAGS=\"-Ctarget-cpu=haswell\"` environment variable to enable AVX instructions.\n\nWe support ARM AArch64 NEON as well and there is no need to pass any additional flags.\n\nYou can find more information in [benches/README.md](./benches/README.md).\n\n## Rendering quality\n\nUnless there is a bug, `tiny-skia` must produce exactly the same results as Skia.\n\n## Safety\n\nWhile a quick search would shown tons of `unsafe`, the library is actually fully safe.\nAll pixels access is bound-checked. And all memory-related operations are safe.\n\nWe must use `unsafe` to call SIMD intrinsics, which is perfectly safe,\nbut Rust's std still marks them as `unsafe` because they may be missing on the target CPU.\nWe do check for that.\n\nWe also have to mark some types (to cast `[u32; 1]` to `[u8; 4]` and vise-versa) as\n[bytemuck::Pod](https://docs.rs/bytemuck/1.4.1/bytemuck/trait.Pod.html),\nwhich is an `unsafe` trait, but still is perfectly safe.\n\n## Out of scope\n\nSkia is a huge library and we support only a tiny part of.\nAnd more importantly, we do not plan to support many feature at all.\n\n- GPU rendering.\n- Text rendering (maybe someday).\n- PDF generation.\n- Non-RGBA8888 images.\n- Non-PNG image formats.\n- Advanced Bézier path operations.\n- Conic path segments.\n- Path effects (except dashing).\n- Any kind of resource caching.\n- ICC profiles.\n\n## Notable changes\n\nDespite being a port, we still have a lot of changes even in the supported subset.\n\n- No global alpha.\u003cbr/\u003e\n  Unlike Skia, only `Pattern` is allowed to have opacity.\n  In all other cases you should adjust colors opacity manually.\n- No bilinear + mipmap down-scaling support.\n- `tiny-skia` uses just a simple alpha mask for clipping, while Skia has a very complicated,\nbut way faster algorithm.\n\n## Notes about the port\n\n`tiny-skia` should be viewed as a Rust 2D rendering library that uses Skia algorithms internally.\nWe have a completely different public API. The internals are also extremely simplified.\nBut all the core logic and math is borrowed from Skia. Hence the name.\n\nAs for the porting process itself, Skia uses goto, inheritance, virtual methods, linked lists,\nconst generics and templates specialization a lot, and all of this features are unavailable in Rust.\nThere are also a lot of pointers magic, implicit mutations and caches.\nTherefore we have to compromise or even rewrite some parts from scratch.\n\n## Alternatives\n\nRight now, the only pure Rust alternative is [raqote].\n\n- It doesn't support high-quality antialiasing (hairline stroking in particular).\n- It's very slow (see [benchmarks](./benches/README.md)).\n- There are some rendering issues (like gradient transparency).\n- Raqote has a very rudimentary text rendering support, while tiny-skia has none.\n\n## License\n\nThe same as used by [Skia]: [New BSD License](./LICENSE)\n\n[Skia]: https://skia.org/\n[cairo]: https://www.cairographics.org/\n[raqote]: https://github.com/jrmuizel/raqote\n[resvg]: https://github.com/linebender/resvg\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinebender%2Ftiny-skia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flinebender%2Ftiny-skia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinebender%2Ftiny-skia/lists"}