Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
sdf_atlas.hpp
Go to the documentation of this file.
1#pragma once
2
3// Signed Distance Field glyph atlas.
4//
5// The goal is resolution-independent text rendering: rasterize each
6// glyph once into a fixed-size SDF tile, then sample the atlas at
7// runtime with a smoothstep shader to produce a crisp edge at any
8// scale. Replaces the per-pixel-size bitmap atlas approach.
9//
10// This header defines the API. The implementation in sdf_atlas.cpp produces
11// SDF tiles by rasterizing the glyph at high resolution and running a
12// Euclidean distance transform (Felzenszwalb & Huttenlocher, 2004) over the
13// resulting mask. Canvas samples the atlas directly; software-renderer and
14// demo paths use the shared SDF text-quad helpers, and SkSL shaders share the
15// same sampler contract.
16
17#include <cstdint>
18#include <memory>
19#include <string>
20#include <vector>
21
22namespace pulp::canvas {
23
24// One glyph's location and metrics inside an SDF atlas.
25struct SdfGlyph {
26 char32_t codepoint = 0;
27 int atlas_x = 0; // top-left in atlas pixels
28 int atlas_y = 0;
29 int width = 0; // tile width in atlas pixels
30 int height = 0; // tile height in atlas pixels
31 float bearing_x = 0.0f; // left side bearing (pixels at base size)
32 float bearing_y = 0.0f; // top bearing (positive up)
33 float advance = 0.0f; // glyph advance (pixels at base size)
34};
35
36// Single-channel SDF atlas. Each texel stores the signed distance
37// from the texel center to the nearest glyph edge, mapped to
38// [0, 255] where 128 = on the edge.
39class SdfAtlas {
40public:
43
44 SdfAtlas(const SdfAtlas&) = delete;
45 SdfAtlas& operator=(const SdfAtlas&) = delete;
46 SdfAtlas(SdfAtlas&&) noexcept;
47 SdfAtlas& operator=(SdfAtlas&&) noexcept;
48
49 // Build an atlas containing every glyph in `chars`. The atlas is
50 // rendered at `base_size` pixels per em with `padding` texels of
51 // empty space around each glyph (the SDF spread radius).
52 //
53 // `font_family` is resolved via the same path as canvas text
54 // rendering, so any font visible to SkFontMgr will work. Returns
55 // false if the font could not be loaded or the resulting atlas
56 // would exceed `max_atlas_size` on either axis.
57 bool build(const std::string& font_family,
58 const std::vector<char32_t>& chars,
59 int base_size = 48,
60 int padding = 8,
61 int max_atlas_size = 2048);
62
63 // Look up an SDF glyph by codepoint. Returns nullptr if the glyph
64 // was not in the build set.
65 const SdfGlyph* glyph(char32_t codepoint) const;
66
67 // Atlas image data. One byte per texel, row-major, no padding.
68 // `width()` * `height()` bytes long. The buffer is owned by the
69 // atlas and is valid for its lifetime.
70 const std::uint8_t* pixels() const;
71 int width() const;
72 int height() const;
73
74 // Number of glyphs successfully packed into the atlas.
75 std::size_t glyph_count() const;
76
77 // Base font size the atlas was built at. Glyph metrics are
78 // expressed in pixels at this size; downstream code that draws at
79 // a different size scales the metrics linearly and the SDF shader
80 // smooths the edges.
81 int base_size() const;
82
83private:
84 struct Impl;
85 std::unique_ptr<Impl> impl_;
86};
87
88} // namespace pulp::canvas
const SdfGlyph * glyph(char32_t codepoint) const
bool build(const std::string &font_family, const std::vector< char32_t > &chars, int base_size=48, int padding=8, int max_atlas_size=2048)
SdfAtlas(const SdfAtlas &)=delete
const std::uint8_t * pixels() const
SdfAtlas & operator=(const SdfAtlas &)=delete
SdfAtlas(SdfAtlas &&) noexcept
std::size_t glyph_count() const
Definition affine_transform.hpp:24
STL namespace.
Definition sdf_atlas.hpp:25
float advance
Definition sdf_atlas.hpp:33
char32_t codepoint
Definition sdf_atlas.hpp:26
int height
Definition sdf_atlas.hpp:30
int width
Definition sdf_atlas.hpp:29
int atlas_x
Definition sdf_atlas.hpp:27
float bearing_x
Definition sdf_atlas.hpp:31
float bearing_y
Definition sdf_atlas.hpp:32
int atlas_y
Definition sdf_atlas.hpp:28