Source code
Revision control
Copy as Markdown
Other Tools
static const char *hb_gpu_fragment_hlsl =
"/*\n"
" * Copyright (C) 2026 Behdad Esfahbod\n"
" * Copyright (C) 2017 Eric Lengyel\n"
" *\n"
" * Based on the Slug algorithm by Eric Lengyel:\n"
" *\n"
" * This is part of HarfBuzz, a text shaping library.\n"
" *\n"
" * Permission is hereby granted, without written agreement and without\n"
" * license or royalty fees, to use, copy, modify, and distribute this\n"
" * software and its documentation for any purpose, provided that the\n"
" * above copyright notice and the following two paragraphs appear in\n"
" * all copies of this software.\n"
" *\n"
" * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\n"
" * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\n"
" * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\n"
" * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\n"
" * DAMAGE.\n"
" *\n"
" * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\n"
" * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n"
" * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\n"
" * ON AN \"AS IS\" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\n"
" * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\n"
" */\n"
"\n"
"\n"
"/* Requires Shader Model 5.0+.\n"
" *\n"
" * The caller must declare:\n"
" * StructuredBuffer<int4> hb_gpu_atlas : register(t0);\n"
" */\n"
"\n"
"\n"
"#ifndef HB_GPU_UNITS_PER_EM\n"
"#define HB_GPU_UNITS_PER_EM 4\n"
"#endif\n"
"\n"
"#define HB_GPU_INV_UNITS (1.0 / (float) HB_GPU_UNITS_PER_EM)\n"
"\n"
"\n"
"int4 hb_gpu_fetch (int offset)\n"
"{\n"
" return hb_gpu_atlas[offset];\n"
"}\n"
"\n"
"\n"
"uint _hb_gpu_calc_root_code (float y1, float y2, float y3)\n"
"{\n"
" uint i1 = asuint (y1) >> 31u;\n"
" uint i2 = asuint (y2) >> 30u;\n"
" uint i3 = asuint (y3) >> 29u;\n"
"\n"
" uint shift = (i2 & 2u) | (i1 & ~2u);\n"
" shift = (i3 & 4u) | (shift & ~4u);\n"
"\n"
" return (0x2E74u >> shift) & 0x0101u;\n"
"}\n"
"\n"
"float2 _hb_gpu_solve_horiz_poly (float2 a, float2 b, float2 p1)\n"
"{\n"
" float ra = 1.0 / a.y;\n"
" float rb = 0.5 / b.y;\n"
"\n"
" float d = sqrt (max (b.y * b.y - a.y * p1.y, 0.0));\n"
" float t1 = (b.y - d) * ra;\n"
" float t2 = (b.y + d) * ra;\n"
"\n"
" if (a.y == 0.0)\n"
" t1 = t2 = p1.y * rb;\n"
"\n"
" return float2 ((a.x * t1 - b.x * 2.0) * t1 + p1.x,\n"
" (a.x * t2 - b.x * 2.0) * t2 + p1.x);\n"
"}\n"
"\n"
"float2 _hb_gpu_solve_vert_poly (float2 a, float2 b, float2 p1)\n"
"{\n"
" float ra = 1.0 / a.x;\n"
" float rb = 0.5 / b.x;\n"
"\n"
" float d = sqrt (max (b.x * b.x - a.x * p1.x, 0.0));\n"
" float t1 = (b.x - d) * ra;\n"
" float t2 = (b.x + d) * ra;\n"
"\n"
" if (a.x == 0.0)\n"
" t1 = t2 = p1.x * rb;\n"
"\n"
" return float2 ((a.y * t1 - b.y * 2.0) * t1 + p1.y,\n"
" (a.y * t2 - b.y * 2.0) * t2 + p1.y);\n"
"}\n"
"\n"
"float _hb_gpu_calc_coverage (float xcov, float ycov, float xwgt, float ywgt)\n"
"{\n"
" float coverage = max (abs (xcov * xwgt + ycov * ywgt) /\n"
" max (xwgt + ywgt, 1.0 / 65536.0),\n"
" min (abs (xcov), abs (ycov)));\n"
"\n"
" return clamp (coverage, 0.0, 1.0);\n"
"}\n"
"\n"
"\n"
"struct _hb_gpu_glyph_info\n"
"{\n"
" int glyphLoc;\n"
" int bandBase;\n"
" int2 bandIndex;\n"
" int numHBands;\n"
" int numVBands;\n"
"};\n"
"\n"
"_hb_gpu_glyph_info _hb_gpu_decode_glyph (float2 renderCoord, uint glyphLoc_)\n"
"{\n"
" _hb_gpu_glyph_info gi;\n"
" gi.glyphLoc = (int) glyphLoc_;\n"
"\n"
" int4 header0 = hb_gpu_fetch (gi.glyphLoc);\n"
" int4 header1 = hb_gpu_fetch (gi.glyphLoc + 1);\n"
" float4 ext = (float4) header0 * HB_GPU_INV_UNITS;\n"
" gi.numHBands = header1.r;\n"
" gi.numVBands = header1.g;\n"
"\n"
" float2 extSize = ext.zw - ext.xy;\n"
" float2 bandScale = float2 ((float) gi.numVBands, (float) gi.numHBands) / max (extSize, float2 (1.0 / 65536.0, 1.0 / 65536.0));\n"
" float2 bandOffset = -ext.xy * bandScale;\n"
"\n"
" gi.bandIndex = clamp ((int2) (renderCoord * bandScale + bandOffset),\n"
" int2 (0, 0),\n"
" int2 (gi.numVBands - 1, gi.numHBands - 1));\n"
"\n"
" gi.bandBase = gi.glyphLoc + 2;\n"
" return gi;\n"
"}\n"
"\n"
"int2 _hb_gpu_curve_counts (float2 renderCoord, uint glyphLoc_)\n"
"{\n"
" _hb_gpu_glyph_info gi = _hb_gpu_decode_glyph (renderCoord, glyphLoc_);\n"
" int hCount = hb_gpu_fetch (gi.bandBase + gi.bandIndex.y).r;\n"
" int vCount = hb_gpu_fetch (gi.bandBase + gi.numHBands + gi.bandIndex.x).r;\n"
" return int2 (hCount, vCount);\n"
"}\n"
"\n"
"\n"
"/* Return coverage in [0, 1].\n"
" *\n"
" * Caller must declare: StructuredBuffer<int4> hb_gpu_atlas\n"
" *\n"
" * renderCoord: em-space sample position\n"
" * glyphLoc: texel offset of glyph blob in atlas\n"
" */\n"
"float hb_gpu_render (float2 renderCoord, uint glyphLoc_)\n"
"{\n"
" float2 emsPerPixel = fwidth (renderCoord);\n"
" float2 pixelsPerEm = 1.0 / emsPerPixel;\n"
"\n"
" _hb_gpu_glyph_info gi = _hb_gpu_decode_glyph (renderCoord, glyphLoc_);\n"
" int glyphLoc = gi.glyphLoc;\n"
" int bandBase = gi.bandBase;\n"
" int numHBands = gi.numHBands;\n"
"\n"
" float xcov = 0.0;\n"
" float xwgt = 0.0;\n"
"\n"
" int4 hbandData = hb_gpu_fetch (bandBase + gi.bandIndex.y);\n"
" int hCurveCount = hbandData.r;\n"
" float hSplit = (float) hbandData.a * HB_GPU_INV_UNITS;\n"
" bool hLeftRay = (renderCoord.x < hSplit);\n"
" int hDataOffset = (hLeftRay ? hbandData.b : hbandData.g) + 32768;\n"
"\n"
" for (int ci = 0; ci < hCurveCount; ci++)\n"
" {\n"
" int curveOffset = hb_gpu_fetch (glyphLoc + hDataOffset + ci).r + 32768;\n"
"\n"
" int4 raw12 = hb_gpu_fetch (glyphLoc + curveOffset);\n"
" int4 raw3 = hb_gpu_fetch (glyphLoc + curveOffset + 1);\n"
"\n"
" float4 q12 = (float4) raw12 * HB_GPU_INV_UNITS;\n"
" float2 q3 = (float2) raw3.rg * HB_GPU_INV_UNITS;\n"
"\n"
" float4 p12 = q12 - float4 (renderCoord, renderCoord);\n"
" float2 p3 = q3 - renderCoord;\n"
"\n"
" if (hLeftRay) {\n"
" if (min (min (p12.x, p12.z), p3.x) * pixelsPerEm.x > 0.5) break;\n"
" } else {\n"
" if (max (max (p12.x, p12.z), p3.x) * pixelsPerEm.x < -0.5) break;\n"
" }\n"
"\n"
" uint code = _hb_gpu_calc_root_code (p12.y, p12.w, p3.y);\n"
" if (code != 0u)\n"
" {\n"
" float2 a = q12.xy - q12.zw * 2.0 + q3;\n"
" float2 b = q12.xy - q12.zw;\n"
" float2 r = _hb_gpu_solve_horiz_poly (a, b, p12.xy) * pixelsPerEm.x;\n"
" float2 cov = hLeftRay ? clamp (float2 (0.5, 0.5) - r, 0.0, 1.0)\n"
" : clamp (r + float2 (0.5, 0.5), 0.0, 1.0);\n"
"\n"
" if ((code & 1u) != 0u)\n"
" {\n"
" xcov += cov.x;\n"
" xwgt = max (xwgt, clamp (1.0 - abs (r.x) * 2.0, 0.0, 1.0));\n"
" }\n"
"\n"
" if (code > 1u)\n"
" {\n"
" xcov -= cov.y;\n"
" xwgt = max (xwgt, clamp (1.0 - abs (r.y) * 2.0, 0.0, 1.0));\n"
" }\n"
" }\n"
" }\n"
"\n"
" float ycov = 0.0;\n"
" float ywgt = 0.0;\n"
"\n"
" int4 vbandData = hb_gpu_fetch (bandBase + numHBands + gi.bandIndex.x);\n"
" int vCurveCount = vbandData.r;\n"
" float vSplit = (float) vbandData.a * HB_GPU_INV_UNITS;\n"
" bool vLeftRay = (renderCoord.y < vSplit);\n"
" int vDataOffset = (vLeftRay ? vbandData.b : vbandData.g) + 32768;\n"
"\n"
" for (int ci = 0; ci < vCurveCount; ci++)\n"
" {\n"
" int curveOffset = hb_gpu_fetch (glyphLoc + vDataOffset + ci).r + 32768;\n"
"\n"
" int4 raw12 = hb_gpu_fetch (glyphLoc + curveOffset);\n"
" int4 raw3 = hb_gpu_fetch (glyphLoc + curveOffset + 1);\n"
"\n"
" float4 q12 = (float4) raw12 * HB_GPU_INV_UNITS;\n"
" float2 q3 = (float2) raw3.rg * HB_GPU_INV_UNITS;\n"
"\n"
" float4 p12 = q12 - float4 (renderCoord, renderCoord);\n"
" float2 p3 = q3 - renderCoord;\n"
"\n"
" if (vLeftRay) {\n"
" if (min (min (p12.y, p12.w), p3.y) * pixelsPerEm.y > 0.5) break;\n"
" } else {\n"
" if (max (max (p12.y, p12.w), p3.y) * pixelsPerEm.y < -0.5) break;\n"
" }\n"
"\n"
" uint code = _hb_gpu_calc_root_code (p12.x, p12.z, p3.x);\n"
" if (code != 0u)\n"
" {\n"
" float2 a = q12.xy - q12.zw * 2.0 + q3;\n"
" float2 b = q12.xy - q12.zw;\n"
" float2 r = _hb_gpu_solve_vert_poly (a, b, p12.xy) * pixelsPerEm.y;\n"
" float2 cov = vLeftRay ? clamp (float2 (0.5, 0.5) - r, 0.0, 1.0)\n"
" : clamp (r + float2 (0.5, 0.5), 0.0, 1.0);\n"
"\n"
" if ((code & 1u) != 0u)\n"
" {\n"
" ycov -= cov.x;\n"
" ywgt = max (ywgt, clamp (1.0 - abs (r.x) * 2.0, 0.0, 1.0));\n"
" }\n"
"\n"
" if (code > 1u)\n"
" {\n"
" ycov += cov.y;\n"
" ywgt = max (ywgt, clamp (1.0 - abs (r.y) * 2.0, 0.0, 1.0));\n"
" }\n"
" }\n"
" }\n"
"\n"
" return _hb_gpu_calc_coverage (xcov, ycov, xwgt, ywgt);\n"
"}\n"
"\n"
"/* Stem darkening for small sizes.\n"
" *\n"
" * coverage: output of hb_gpu_render\n"
" * brightness: foreground brightness in [0, 1]\n"
" * ppem: pixels per em at this fragment\n"
" */\n"
"float hb_gpu_darken (float coverage, float brightness, float ppem)\n"
"{\n"
" return pow (coverage,\n"
" lerp (pow (2.0, brightness - 0.5), 1.0,\n"
" smoothstep (8.0, 48.0, ppem)));\n"
"}\n"
;