| /* |
| * Copyright 2026 Behdad Esfahbod. All Rights Reserved. |
| */ |
| |
| #ifndef DEMO_SHADERS_H |
| #define DEMO_SHADERS_H |
| |
| #include "demo-common.h" |
| #include "demo-font.h" |
| |
| |
| struct glyph_vertex_t { |
| /* Object-space position */ |
| GLfloat x; |
| GLfloat y; |
| /* Em-space texture coordinates */ |
| GLfloat tx; |
| GLfloat ty; |
| /* Object-space outward normal at this vertex */ |
| GLfloat nx; |
| GLfloat ny; |
| /* Em units per object-space unit (upem / font_size) */ |
| GLfloat emPerPos; |
| /* Atlas offset (constant across glyph) */ |
| GLuint atlas_offset; |
| }; |
| |
| static inline void |
| demo_shader_add_glyph_vertices (const demo_point_t &p, |
| double font_size, |
| glyph_info_t *gi, |
| std::vector<glyph_vertex_t> *vertices, |
| demo_extents_t *extents) |
| { |
| if (gi->is_empty) |
| return; |
| |
| double scale = font_size / gi->upem; |
| |
| glyph_vertex_t v[4]; |
| |
| for (int ci = 0; ci < 4; ci++) { |
| int cx = (ci >> 1) & 1; |
| int cy = ci & 1; |
| |
| double ex = (1 - cx) * gi->extents.min_x + cx * gi->extents.max_x; |
| double ey = (1 - cy) * gi->extents.min_y + cy * gi->extents.max_y; |
| |
| v[ci].x = (float) (p.x + scale * ex); |
| v[ci].y = (float) (p.y - scale * ey); |
| v[ci].tx = (float) ex; |
| v[ci].ty = (float) ey; |
| v[ci].nx = cx ? 1.f : -1.f; |
| v[ci].ny = cy ? -1.f : 1.f; |
| v[ci].emPerPos = (float) (1.0 / scale); |
| v[ci].atlas_offset = gi->atlas_offset; |
| } |
| |
| vertices->push_back (v[0]); |
| vertices->push_back (v[1]); |
| vertices->push_back (v[2]); |
| |
| vertices->push_back (v[1]); |
| vertices->push_back (v[2]); |
| vertices->push_back (v[3]); |
| |
| if (extents) { |
| demo_extents_clear (extents); |
| for (int i = 0; i < 4; i++) { |
| demo_point_t pt = {(double) v[i].x, (double) v[i].y}; |
| demo_extents_add (extents, &pt); |
| } |
| } |
| } |
| |
| |
| GLuint |
| demo_shader_create_program (bool draw_only); |
| |
| |
| #endif /* DEMO_SHADERS_H */ |