citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

commit 21c03b9b80b6ea306ad0946614463d0bc268d546
parent 4b05f3cea583f60f8ad3817cde5a9970c89c7e0c
Author: Kyle Milz <kyle@0x30.net>
Date:   Tue, 19 Jul 2016 19:44:19 -0600

src: use raw glsl files

Diffstat:
MJamrules | 13+++++++++++++
Msrc/Jamfile | 4++++
Dsrc/demo-atlas-glsl.h | 18------------------
Dsrc/demo-fshader-glsl.h | 87-------------------------------------------------------------------------------
Msrc/demo-shader.cc | 6+++---
Dsrc/demo-vshader-glsl.h | 24------------------------
Asrc/demo_atlas.glsl | 16++++++++++++++++
Asrc/demo_fshader.glsl | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/demo_vshader.glsl | 22++++++++++++++++++++++
Msrc/glyphy/Jamfile | 3+++
Dsrc/glyphy/glyphy-common-glsl.h | 224-------------------------------------------------------------------------------
Asrc/glyphy/glyphy-common.glsl | 222+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/glyphy/glyphy-sdf-glsl.h | 152-------------------------------------------------------------------------------
Asrc/glyphy/glyphy-sdf.glsl | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/glyphy/glyphy-shaders.cc | 4++--
Asrc/stringize | 17+++++++++++++++++
16 files changed, 537 insertions(+), 510 deletions(-)

diff --git a/Jamrules b/Jamrules @@ -103,6 +103,19 @@ actions Test { Test test : ; Test regress : ; +rule Stringize +{ + MakeLocate $(1) : $(LOCATE_SOURCE) ; + SEARCH on $(2) = $(SEARCH_SOURCE) ; + Depends $(1) : $(2) ; + Clean clean : $(1) ; +} + +actions Stringize +{ + $(TOP)/src/stringize "static const char *$(1:B)" $(2) > $(1) ; +} + echo ...build citrun ($(OS))... ; echo " C++= $(C++)" ; echo " CITRUN_LIB= $(CITRUN_LIB)" ; diff --git a/src/Jamfile b/src/Jamfile @@ -54,6 +54,10 @@ INST_SRCS = inst_action.cc inst_ast_visitor.cc ; +Stringize demo_atlas_glsl.h : demo_atlas.glsl ; +Stringize demo_vshader_glsl.h : demo_vshader.glsl ; +Stringize demo_fshader_glsl.h : demo_fshader.glsl ; + # Older llvm-config doesn't add -std=c++11 ObjectC++Flags $(INST_SRCS) : -std=c++11 `llvm-config --cxxflags` ; ObjectC++Flags $(INST_SRCS) : -DCITRUN_LIB=$(CITRUN_LIB) -DCITRUN_PATH=$(CITRUN_PATH) ; diff --git a/src/demo-atlas-glsl.h b/src/demo-atlas-glsl.h @@ -1,18 +0,0 @@ -static const char *demo_atlas_glsl = -"uniform sampler2D u_atlas_tex;\n" -"uniform ivec4 u_atlas_info;\n" -"\n" -"#define GLYPHY_TEXTURE1D_EXTRA_DECLS , sampler2D _tex, ivec4 _atlas_info, ivec2 _atlas_pos\n" -"#define GLYPHY_TEXTURE1D_EXTRA_ARGS , _tex, _atlas_info, _atlas_pos\n" -"#define GLYPHY_DEMO_EXTRA_ARGS , u_atlas_tex, u_atlas_info, gi.atlas_pos\n" -"\n" -"vec4\n" -"glyphy_texture1D_func (int offset GLYPHY_TEXTURE1D_EXTRA_DECLS)\n" -"{\n" -" ivec2 item_geom = _atlas_info.zw;\n" -" vec2 pos = (vec2 (_atlas_pos.xy * item_geom +\n" -" ivec2 (mod (float (offset), float (item_geom.x)), offset / item_geom.x)) +\n" -" + vec2 (.5, .5)) / vec2(_atlas_info.xy);\n" -" return texture2D (_tex, pos);\n" -"}\n" -; diff --git a/src/demo-fshader-glsl.h b/src/demo-fshader-glsl.h @@ -1,87 +0,0 @@ -static const char *demo_fshader_glsl = -"uniform float u_contrast;\n" -"uniform float u_gamma_adjust;\n" -"uniform float u_outline_thickness;\n" -"uniform bool u_outline;\n" -"uniform float u_boldness;\n" -"uniform bool u_debug;\n" -"\n" -"varying vec4 v_glyph;\n" -"\n" -"\n" -"#define SQRT2_2 0.70710678118654757 /* 1 / sqrt(2.) */\n" -"#define SQRT2 1.4142135623730951\n" -"\n" -"struct glyph_info_t {\n" -" ivec2 nominal_size;\n" -" ivec2 atlas_pos;\n" -"};\n" -"\n" -"glyph_info_t\n" -"glyph_info_decode (vec4 v)\n" -"{\n" -" glyph_info_t gi;\n" -" gi.nominal_size = (ivec2 (mod (v.zw, 256.)) + 2) / 4;\n" -" gi.atlas_pos = ivec2 (v_glyph.zw) / 256;\n" -" return gi;\n" -"}\n" -"\n" -"\n" -"float\n" -"antialias (float d)\n" -"{\n" -" return smoothstep (-.75, +.75, d);\n" -"}\n" -"\n" -"void\n" -"main()\n" -"{\n" -" vec2 p = v_glyph.xy;\n" -" glyph_info_t gi = glyph_info_decode (v_glyph);\n" -"\n" -" /* isotropic antialiasing */\n" -" vec2 dpdx = dFdx (p);\n" -" vec2 dpdy = dFdy (p);\n" -" float m = length (vec2 (length (dpdx), length (dpdy))) * SQRT2_2;\n" -"\n" -" vec4 color = vec4 (0,0,0,1);\n" -"\n" -" float gsdist = glyphy_sdf (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS);\n" -" float sdist = gsdist / m * u_contrast;\n" -"\n" -" if (!u_debug) {\n" -" sdist -= u_boldness * 10.;\n" -" if (u_outline)\n" -" sdist = abs (sdist) - u_outline_thickness * .5;\n" -" if (sdist > 1.)\n" -" discard;\n" -" float alpha = antialias (-sdist);\n" -" if (u_gamma_adjust != 1.)\n" -" alpha = pow (alpha, 1./u_gamma_adjust);\n" -" color = vec4 (color.rgb,color.a * alpha);\n" -" } else {\n" -" color = vec4 (0,0,0,0);\n" -"\n" -" // Color the inside of the glyph a light red\n" -" color += vec4 (.5,0,0,.5) * smoothstep (1., -1., sdist);\n" -"\n" -" float udist = abs (sdist);\n" -" float gudist = abs (gsdist);\n" -" // Color the outline red\n" -" color += vec4 (1,0,0,1) * smoothstep (2., 1., udist);\n" -" // Color the distance field in green\n" -" if (!glyphy_isinf (udist))\n" -" color += vec4(0,.4,0,.4 - (abs(gsdist) / max(float(gi.nominal_size.x), float(gi.nominal_size.y))) * 4.);\n" -"\n" -" float pdist = glyphy_point_dist (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS);\n" -" // Color points green\n" -" color = mix (vec4 (0,1,0,.5), color, smoothstep (.05, .06, pdist));\n" -"\n" -" glyphy_arc_list_t arc_list = glyphy_arc_list (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS);\n" -" // Color the number of endpoints per cell blue\n" -" color += vec4 (0,0,1,.1) * float(arc_list.num_endpoints) * 32./255.;\n" -" }\n" -"\n" -" gl_FragColor = color;\n" -"}\n" -; diff --git a/src/demo-shader.cc b/src/demo-shader.cc @@ -18,9 +18,9 @@ #include "demo-shader.h" -#include "demo-atlas-glsl.h" -#include "demo-vshader-glsl.h" -#include "demo-fshader-glsl.h" +#include "demo_atlas_glsl.h" +#include "demo_vshader_glsl.h" +#include "demo_fshader_glsl.h" diff --git a/src/demo-vshader-glsl.h b/src/demo-vshader-glsl.h @@ -1,24 +0,0 @@ -static const char *demo_vshader_glsl = -"uniform mat4 u_matViewProjection;\n" -"\n" -"attribute vec4 a_glyph_vertex;\n" -"\n" -"varying vec4 v_glyph;\n" -"\n" -"vec4\n" -"glyph_vertex_transcode (vec2 v)\n" -"{\n" -" ivec2 g = ivec2 (v);\n" -" ivec2 corner = ivec2 (mod (v, 2.));\n" -" g /= 2;\n" -" ivec2 nominal_size = ivec2 (mod (vec2(g), 64.));\n" -" return vec4 (corner * nominal_size, g * 4);\n" -"}\n" -"\n" -"void\n" -"main()\n" -"{\n" -" gl_Position = u_matViewProjection * vec4 (a_glyph_vertex.xy, 0, 1);\n" -" v_glyph = glyph_vertex_transcode (a_glyph_vertex.zw);\n" -"}\n" -; diff --git a/src/demo_atlas.glsl b/src/demo_atlas.glsl @@ -0,0 +1,16 @@ +uniform sampler2D u_atlas_tex; +uniform ivec4 u_atlas_info; + +#define GLYPHY_TEXTURE1D_EXTRA_DECLS , sampler2D _tex, ivec4 _atlas_info, ivec2 _atlas_pos +#define GLYPHY_TEXTURE1D_EXTRA_ARGS , _tex, _atlas_info, _atlas_pos +#define GLYPHY_DEMO_EXTRA_ARGS , u_atlas_tex, u_atlas_info, gi.atlas_pos + +vec4 +glyphy_texture1D_func (int offset GLYPHY_TEXTURE1D_EXTRA_DECLS) +{ + ivec2 item_geom = _atlas_info.zw; + vec2 pos = (vec2 (_atlas_pos.xy * item_geom + + ivec2 (mod (float (offset), float (item_geom.x)), offset / item_geom.x)) + + + vec2 (.5, .5)) / vec2(_atlas_info.xy); + return texture2D (_tex, pos); +} diff --git a/src/demo_fshader.glsl b/src/demo_fshader.glsl @@ -0,0 +1,85 @@ +uniform float u_contrast; +uniform float u_gamma_adjust; +uniform float u_outline_thickness; +uniform bool u_outline; +uniform float u_boldness; +uniform bool u_debug; + +varying vec4 v_glyph; + + +#define SQRT2_2 0.70710678118654757 /* 1 / sqrt(2.) */ +#define SQRT2 1.4142135623730951 + +struct glyph_info_t { + ivec2 nominal_size; + ivec2 atlas_pos; +}; + +glyph_info_t +glyph_info_decode (vec4 v) +{ + glyph_info_t gi; + gi.nominal_size = (ivec2 (mod (v.zw, 256.)) + 2) / 4; + gi.atlas_pos = ivec2 (v_glyph.zw) / 256; + return gi; +} + + +float +antialias (float d) +{ + return smoothstep (-.75, +.75, d); +} + +void +main() +{ + vec2 p = v_glyph.xy; + glyph_info_t gi = glyph_info_decode (v_glyph); + + /* isotropic antialiasing */ + vec2 dpdx = dFdx (p); + vec2 dpdy = dFdy (p); + float m = length (vec2 (length (dpdx), length (dpdy))) * SQRT2_2; + + vec4 color = vec4 (0,0,0,1); + + float gsdist = glyphy_sdf (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS); + float sdist = gsdist / m * u_contrast; + + if (!u_debug) { + sdist -= u_boldness * 10.; + if (u_outline) + sdist = abs (sdist) - u_outline_thickness * .5; + if (sdist > 1.) + discard; + float alpha = antialias (-sdist); + if (u_gamma_adjust != 1.) + alpha = pow (alpha, 1./u_gamma_adjust); + color = vec4 (color.rgb,color.a * alpha); + } else { + color = vec4 (0,0,0,0); + + // Color the inside of the glyph a light red + color += vec4 (.5,0,0,.5) * smoothstep (1., -1., sdist); + + float udist = abs (sdist); + float gudist = abs (gsdist); + // Color the outline red + color += vec4 (1,0,0,1) * smoothstep (2., 1., udist); + // Color the distance field in green + if (!glyphy_isinf (udist)) + color += vec4(0,.4,0,.4 - (abs(gsdist) / max(float(gi.nominal_size.x), float(gi.nominal_size.y))) * 4.); + + float pdist = glyphy_point_dist (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS); + // Color points green + color = mix (vec4 (0,1,0,.5), color, smoothstep (.05, .06, pdist)); + + glyphy_arc_list_t arc_list = glyphy_arc_list (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS); + // Color the number of endpoints per cell blue + color += vec4 (0,0,1,.1) * float(arc_list.num_endpoints) * 32./255.; + } + + gl_FragColor = color; +} diff --git a/src/demo_vshader.glsl b/src/demo_vshader.glsl @@ -0,0 +1,22 @@ +uniform mat4 u_matViewProjection; + +attribute vec4 a_glyph_vertex; + +varying vec4 v_glyph; + +vec4 +glyph_vertex_transcode (vec2 v) +{ + ivec2 g = ivec2 (v); + ivec2 corner = ivec2 (mod (v, 2.)); + g /= 2; + ivec2 nominal_size = ivec2 (mod (vec2(g), 64.)); + return vec4 (corner * nominal_size, g * 4); +} + +void +main() +{ + gl_Position = u_matViewProjection * vec4 (a_glyph_vertex.xy, 0, 1); + v_glyph = glyph_vertex_transcode (a_glyph_vertex.zw); +} diff --git a/src/glyphy/Jamfile b/src/glyphy/Jamfile @@ -10,3 +10,6 @@ Library libglyphy : glyphy-arc.cc glyphy-outline.cc glyphy-sdf.cc glyphy-shaders.cc ; + +Stringize glyphy_common_glsl.h : glyphy-common.glsl ; +Stringize glyphy_sdf_glsl.h : glyphy-sdf.glsl ; diff --git a/src/glyphy/glyphy-common-glsl.h b/src/glyphy/glyphy-common-glsl.h @@ -1,224 +0,0 @@ -static const char *glyphy_common_glsl = -"/*\n" -" * Copyright 2012 Google, Inc. All Rights Reserved.\n" -" *\n" -" * Licensed under the Apache License, Version 2.0 (the \"License\");\n" -" * you may not use this file except in compliance with the License.\n" -" * You may obtain a copy of the License at\n" -" *\n" -" * http://www.apache.org/licenses/LICENSE-2.0\n" -" *\n" -" * Unless required by applicable law or agreed to in writing, software\n" -" * distributed under the License is distributed on an \"AS IS\" BASIS,\n" -" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -" * See the License for the specific language governing permissions and\n" -" * limitations under the License.\n" -" *\n" -" * Google Author(s): Behdad Esfahbod, Maysum Panju\n" -" */\n" -"\n" -"\n" -"#ifndef GLYPHY_INFINITY\n" -"# define GLYPHY_INFINITY 1e9\n" -"#endif\n" -"#ifndef GLYPHY_EPSILON\n" -"# define GLYPHY_EPSILON 1e-5\n" -"#endif\n" -"\n" -"#ifndef GLYPHY_RGBA\n" -"# ifdef GLYPHY_BGRA\n" -"# define GLYPHY_RGBA(v) glyphy_bgra (v)\n" -"# else\n" -"# define GLYPHY_RGBA(v) glyphy_rgba (v)\n" -"# endif\n" -"#endif\n" -"\n" -"vec4\n" -"glyphy_rgba (const vec4 v)\n" -"{\n" -" return v.rgba;\n" -"}\n" -"\n" -"vec4\n" -"glyphy_bgra (const vec4 v)\n" -"{\n" -" return v.bgra;\n" -"}\n" -"\n" -"\n" -"struct glyphy_arc_t {\n" -" vec2 p0;\n" -" vec2 p1;\n" -" float d;\n" -"};\n" -"\n" -"struct glyphy_arc_endpoint_t {\n" -" /* Second arc endpoint */\n" -" vec2 p;\n" -" /* Infinity if this endpoint does not form an arc with the previous\n" -" * endpoint. Ie. a \"move_to\". Test with glyphy_isinf().\n" -" * Arc depth otherwise. */\n" -" float d;\n" -"};\n" -"\n" -"struct glyphy_arc_list_t {\n" -" /* Number of endpoints in the list.\n" -" * Will be zero if we're far away inside or outside, in which case side is set.\n" -" * Will be -1 if this arc-list encodes a single line, in which case line_* are set. */\n" -" int num_endpoints;\n" -"\n" -" /* If num_endpoints is zero, this specifies whether we are inside (-1)\n" -" * or outside (+1). Otherwise we're unsure (0). */\n" -" int side;\n" -" /* Offset to the arc-endpoints from the beginning of the glyph blob */\n" -" int offset;\n" -"\n" -" /* A single line is all we care about. It's right here. */\n" -" float line_angle;\n" -" float line_distance; /* From nominal glyph center */\n" -"};\n" -"\n" -"bool\n" -"glyphy_isinf (const float v)\n" -"{\n" -" return abs (v) >= GLYPHY_INFINITY * .5;\n" -"}\n" -"\n" -"bool\n" -"glyphy_iszero (const float v)\n" -"{\n" -" return abs (v) <= GLYPHY_EPSILON * 2.;\n" -"}\n" -"\n" -"vec2\n" -"glyphy_ortho (const vec2 v)\n" -"{\n" -" return vec2 (-v.y, v.x);\n" -"}\n" -"\n" -"int\n" -"glyphy_float_to_byte (const float v)\n" -"{\n" -" return int (v * (256. - GLYPHY_EPSILON));\n" -"}\n" -"\n" -"ivec4\n" -"glyphy_vec4_to_bytes (const vec4 v)\n" -"{\n" -" return ivec4 (v * (256. - GLYPHY_EPSILON));\n" -"}\n" -"\n" -"ivec2\n" -"glyphy_float_to_two_nimbles (const float v)\n" -"{\n" -" int f = glyphy_float_to_byte (v);\n" -" return ivec2 (f / 16, int(mod (float(f), 16.)));\n" -"}\n" -"\n" -"/* returns tan (2 * atan (d)) */\n" -"float\n" -"glyphy_tan2atan (const float d)\n" -"{\n" -" return 2. * d / (1. - d * d);\n" -"}\n" -"\n" -"glyphy_arc_endpoint_t\n" -"glyphy_arc_endpoint_decode (const vec4 v, const ivec2 nominal_size)\n" -"{\n" -" vec2 p = (vec2 (glyphy_float_to_two_nimbles (v.a)) + v.gb) / 16.;\n" -" float d = v.r;\n" -" if (d == 0.)\n" -" d = GLYPHY_INFINITY;\n" -" else\n" -"#define GLYPHY_MAX_D .5\n" -" d = float(glyphy_float_to_byte (d) - 128) * GLYPHY_MAX_D / 127.;\n" -"#undef GLYPHY_MAX_D\n" -" return glyphy_arc_endpoint_t (p * vec2(nominal_size), d);\n" -"}\n" -"\n" -"vec2\n" -"glyphy_arc_center (const glyphy_arc_t a)\n" -"{\n" -" return mix (a.p0, a.p1, .5) +\n" -" glyphy_ortho (a.p1 - a.p0) / (2. * glyphy_tan2atan (a.d));\n" -"}\n" -"\n" -"bool\n" -"glyphy_arc_wedge_contains (const glyphy_arc_t a, const vec2 p)\n" -"{\n" -" float d2 = glyphy_tan2atan (a.d);\n" -" return dot (p - a.p0, (a.p1 - a.p0) * mat2(1, d2, -d2, 1)) >= 0. &&\n" -" dot (p - a.p1, (a.p1 - a.p0) * mat2(1, -d2, d2, 1)) <= 0.;\n" -"}\n" -"\n" -"float\n" -"glyphy_arc_wedge_signed_dist_shallow (const glyphy_arc_t a, const vec2 p)\n" -"{\n" -" vec2 v = normalize (a.p1 - a.p0);\n" -" float line_d = dot (p - a.p0, glyphy_ortho (v));\n" -" if (a.d == 0.)\n" -" return line_d;\n" -"\n" -" float d0 = dot ((p - a.p0), v);\n" -" if (d0 < 0.)\n" -" return sign (line_d) * distance (p, a.p0);\n" -" float d1 = dot ((a.p1 - p), v);\n" -" if (d1 < 0.)\n" -" return sign (line_d) * distance (p, a.p1);\n" -" float r = 2. * a.d * (d0 * d1) / (d0 + d1);\n" -" if (r * line_d > 0.)\n" -" return sign (line_d) * min (abs (line_d + r), min (distance (p, a.p0), distance (p, a.p1)));\n" -" return line_d + r;\n" -"}\n" -"\n" -"float\n" -"glyphy_arc_wedge_signed_dist (const glyphy_arc_t a, const vec2 p)\n" -"{\n" -" if (abs (a.d) <= .03)\n" -" return glyphy_arc_wedge_signed_dist_shallow (a, p);\n" -" vec2 c = glyphy_arc_center (a);\n" -" return sign (a.d) * (distance (a.p0, c) - distance (p, c));\n" -"}\n" -"\n" -"float\n" -"glyphy_arc_extended_dist (const glyphy_arc_t a, const vec2 p)\n" -"{\n" -" /* Note: this doesn't handle points inside the wedge. */\n" -" vec2 m = mix (a.p0, a.p1, .5);\n" -" float d2 = glyphy_tan2atan (a.d);\n" -" if (dot (p - m, a.p1 - m) < 0.)\n" -" return dot (p - a.p0, normalize ((a.p1 - a.p0) * mat2(+d2, -1, +1, +d2)));\n" -" else\n" -" return dot (p - a.p1, normalize ((a.p1 - a.p0) * mat2(-d2, -1, +1, -d2)));\n" -"}\n" -"\n" -"int\n" -"glyphy_arc_list_offset (const vec2 p, const ivec2 nominal_size)\n" -"{\n" -" ivec2 cell = ivec2 (clamp (floor (p), vec2 (0.,0.), vec2(nominal_size - 1)));\n" -" return cell.y * nominal_size.x + cell.x;\n" -"}\n" -"\n" -"glyphy_arc_list_t\n" -"glyphy_arc_list_decode (const vec4 v, const ivec2 nominal_size)\n" -"{\n" -" glyphy_arc_list_t l;\n" -" ivec4 iv = glyphy_vec4_to_bytes (v);\n" -" l.side = 0; /* unsure */\n" -" if (iv.r == 0) { /* arc-list encoded */\n" -" l.offset = (iv.g * 256) + iv.b;\n" -" l.num_endpoints = iv.a;\n" -" if (l.num_endpoints == 255) {\n" -" l.num_endpoints = 0;\n" -" l.side = -1;\n" -" } else if (l.num_endpoints == 0)\n" -" l.side = +1;\n" -" } else { /* single line encoded */\n" -" l.num_endpoints = -1;\n" -" l.line_distance = float(((iv.r - 128) * 256 + iv.g) - 0x4000) / float (0x1FFF)\n" -" * max (float (nominal_size.x), float (nominal_size.y));\n" -" l.line_angle = float(-((iv.b * 256 + iv.a) - 0x8000)) / float (0x7FFF) * 3.14159265358979;\n" -" }\n" -" return l;\n" -"}\n" -; diff --git a/src/glyphy/glyphy-common.glsl b/src/glyphy/glyphy-common.glsl @@ -0,0 +1,222 @@ +/* + * Copyright 2012 Google, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Google Author(s): Behdad Esfahbod, Maysum Panju + */ + + +#ifndef GLYPHY_INFINITY +# define GLYPHY_INFINITY 1e9 +#endif +#ifndef GLYPHY_EPSILON +# define GLYPHY_EPSILON 1e-5 +#endif + +#ifndef GLYPHY_RGBA +# ifdef GLYPHY_BGRA +# define GLYPHY_RGBA(v) glyphy_bgra (v) +# else +# define GLYPHY_RGBA(v) glyphy_rgba (v) +# endif +#endif + +vec4 +glyphy_rgba (const vec4 v) +{ + return v.rgba; +} + +vec4 +glyphy_bgra (const vec4 v) +{ + return v.bgra; +} + + +struct glyphy_arc_t { + vec2 p0; + vec2 p1; + float d; +}; + +struct glyphy_arc_endpoint_t { + /* Second arc endpoint */ + vec2 p; + /* Infinity if this endpoint does not form an arc with the previous + * endpoint. Ie. a "move_to". Test with glyphy_isinf(). + * Arc depth otherwise. */ + float d; +}; + +struct glyphy_arc_list_t { + /* Number of endpoints in the list. + * Will be zero if we're far away inside or outside, in which case side is set. + * Will be -1 if this arc-list encodes a single line, in which case line_* are set. */ + int num_endpoints; + + /* If num_endpoints is zero, this specifies whether we are inside (-1) + * or outside (+1). Otherwise we're unsure (0). */ + int side; + /* Offset to the arc-endpoints from the beginning of the glyph blob */ + int offset; + + /* A single line is all we care about. It's right here. */ + float line_angle; + float line_distance; /* From nominal glyph center */ +}; + +bool +glyphy_isinf (const float v) +{ + return abs (v) >= GLYPHY_INFINITY * .5; +} + +bool +glyphy_iszero (const float v) +{ + return abs (v) <= GLYPHY_EPSILON * 2.; +} + +vec2 +glyphy_ortho (const vec2 v) +{ + return vec2 (-v.y, v.x); +} + +int +glyphy_float_to_byte (const float v) +{ + return int (v * (256. - GLYPHY_EPSILON)); +} + +ivec4 +glyphy_vec4_to_bytes (const vec4 v) +{ + return ivec4 (v * (256. - GLYPHY_EPSILON)); +} + +ivec2 +glyphy_float_to_two_nimbles (const float v) +{ + int f = glyphy_float_to_byte (v); + return ivec2 (f / 16, int(mod (float(f), 16.))); +} + +/* returns tan (2 * atan (d)) */ +float +glyphy_tan2atan (const float d) +{ + return 2. * d / (1. - d * d); +} + +glyphy_arc_endpoint_t +glyphy_arc_endpoint_decode (const vec4 v, const ivec2 nominal_size) +{ + vec2 p = (vec2 (glyphy_float_to_two_nimbles (v.a)) + v.gb) / 16.; + float d = v.r; + if (d == 0.) + d = GLYPHY_INFINITY; + else +#define GLYPHY_MAX_D .5 + d = float(glyphy_float_to_byte (d) - 128) * GLYPHY_MAX_D / 127.; +#undef GLYPHY_MAX_D + return glyphy_arc_endpoint_t (p * vec2(nominal_size), d); +} + +vec2 +glyphy_arc_center (const glyphy_arc_t a) +{ + return mix (a.p0, a.p1, .5) + + glyphy_ortho (a.p1 - a.p0) / (2. * glyphy_tan2atan (a.d)); +} + +bool +glyphy_arc_wedge_contains (const glyphy_arc_t a, const vec2 p) +{ + float d2 = glyphy_tan2atan (a.d); + return dot (p - a.p0, (a.p1 - a.p0) * mat2(1, d2, -d2, 1)) >= 0. && + dot (p - a.p1, (a.p1 - a.p0) * mat2(1, -d2, d2, 1)) <= 0.; +} + +float +glyphy_arc_wedge_signed_dist_shallow (const glyphy_arc_t a, const vec2 p) +{ + vec2 v = normalize (a.p1 - a.p0); + float line_d = dot (p - a.p0, glyphy_ortho (v)); + if (a.d == 0.) + return line_d; + + float d0 = dot ((p - a.p0), v); + if (d0 < 0.) + return sign (line_d) * distance (p, a.p0); + float d1 = dot ((a.p1 - p), v); + if (d1 < 0.) + return sign (line_d) * distance (p, a.p1); + float r = 2. * a.d * (d0 * d1) / (d0 + d1); + if (r * line_d > 0.) + return sign (line_d) * min (abs (line_d + r), min (distance (p, a.p0), distance (p, a.p1))); + return line_d + r; +} + +float +glyphy_arc_wedge_signed_dist (const glyphy_arc_t a, const vec2 p) +{ + if (abs (a.d) <= .03) + return glyphy_arc_wedge_signed_dist_shallow (a, p); + vec2 c = glyphy_arc_center (a); + return sign (a.d) * (distance (a.p0, c) - distance (p, c)); +} + +float +glyphy_arc_extended_dist (const glyphy_arc_t a, const vec2 p) +{ + /* Note: this doesn't handle points inside the wedge. */ + vec2 m = mix (a.p0, a.p1, .5); + float d2 = glyphy_tan2atan (a.d); + if (dot (p - m, a.p1 - m) < 0.) + return dot (p - a.p0, normalize ((a.p1 - a.p0) * mat2(+d2, -1, +1, +d2))); + else + return dot (p - a.p1, normalize ((a.p1 - a.p0) * mat2(-d2, -1, +1, -d2))); +} + +int +glyphy_arc_list_offset (const vec2 p, const ivec2 nominal_size) +{ + ivec2 cell = ivec2 (clamp (floor (p), vec2 (0.,0.), vec2(nominal_size - 1))); + return cell.y * nominal_size.x + cell.x; +} + +glyphy_arc_list_t +glyphy_arc_list_decode (const vec4 v, const ivec2 nominal_size) +{ + glyphy_arc_list_t l; + ivec4 iv = glyphy_vec4_to_bytes (v); + l.side = 0; /* unsure */ + if (iv.r == 0) { /* arc-list encoded */ + l.offset = (iv.g * 256) + iv.b; + l.num_endpoints = iv.a; + if (l.num_endpoints == 255) { + l.num_endpoints = 0; + l.side = -1; + } else if (l.num_endpoints == 0) + l.side = +1; + } else { /* single line encoded */ + l.num_endpoints = -1; + l.line_distance = float(((iv.r - 128) * 256 + iv.g) - 0x4000) / float (0x1FFF) + * max (float (nominal_size.x), float (nominal_size.y)); + l.line_angle = float(-((iv.b * 256 + iv.a) - 0x8000)) / float (0x7FFF) * 3.14159265358979; + } + return l; +} diff --git a/src/glyphy/glyphy-sdf-glsl.h b/src/glyphy/glyphy-sdf-glsl.h @@ -1,152 +0,0 @@ -static const char *glyphy_sdf_glsl = -"/*\n" -" * Copyright 2012 Google, Inc. All Rights Reserved.\n" -" *\n" -" * Licensed under the Apache License, Version 2.0 (the \"License\");\n" -" * you may not use this file except in compliance with the License.\n" -" * You may obtain a copy of the License at\n" -" *\n" -" * http://www.apache.org/licenses/LICENSE-2.0\n" -" *\n" -" * Unless required by applicable law or agreed to in writing, software\n" -" * distributed under the License is distributed on an \"AS IS\" BASIS,\n" -" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -" * See the License for the specific language governing permissions and\n" -" * limitations under the License.\n" -" *\n" -" * Google Author(s): Behdad Esfahbod, Maysum Panju\n" -" */\n" -"\n" -"#ifndef GLYPHY_TEXTURE1D_FUNC\n" -"#define GLYPHY_TEXTURE1D_FUNC glyphy_texture1D_func\n" -"#endif\n" -"#ifndef GLYPHY_TEXTURE1D_EXTRA_DECLS\n" -"#define GLYPHY_TEXTURE1D_EXTRA_DECLS\n" -"#endif\n" -"#ifndef GLYPHY_TEXTURE1D_EXTRA_ARGS\n" -"#define GLYPHY_TEXTURE1D_EXTRA_ARGS\n" -"#endif\n" -"\n" -"#ifndef GLYPHY_SDF_TEXTURE1D_FUNC\n" -"#define GLYPHY_SDF_TEXTURE1D_FUNC GLYPHY_TEXTURE1D_FUNC\n" -"#endif\n" -"#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS\n" -"#define GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS GLYPHY_TEXTURE1D_EXTRA_DECLS\n" -"#endif\n" -"#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS\n" -"#define GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS GLYPHY_TEXTURE1D_EXTRA_ARGS\n" -"#endif\n" -"#ifndef GLYPHY_SDF_TEXTURE1D\n" -"#define GLYPHY_SDF_TEXTURE1D(offset) GLYPHY_RGBA(GLYPHY_SDF_TEXTURE1D_FUNC (offset GLYPHY_TEXTURE1D_EXTRA_ARGS))\n" -"#endif\n" -"\n" -"#ifndef GLYPHY_MAX_NUM_ENDPOINTS\n" -"#define GLYPHY_MAX_NUM_ENDPOINTS 32\n" -"#endif\n" -"\n" -"glyphy_arc_list_t\n" -"glyphy_arc_list (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)\n" -"{\n" -" int cell_offset = glyphy_arc_list_offset (p, nominal_size);\n" -" vec4 arc_list_data = GLYPHY_SDF_TEXTURE1D (cell_offset);\n" -" return glyphy_arc_list_decode (arc_list_data, nominal_size);\n" -"}\n" -"\n" -"float\n" -"glyphy_sdf (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)\n" -"{\n" -" glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS);\n" -"\n" -" /* Short-circuits */\n" -" if (arc_list.num_endpoints == 0) {\n" -" /* far-away cell */\n" -" return GLYPHY_INFINITY * float(arc_list.side);\n" -" } if (arc_list.num_endpoints == -1) {\n" -" /* single-line */\n" -" float angle = arc_list.line_angle;\n" -" vec2 n = vec2 (cos (angle), sin (angle));\n" -" return dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance;\n" -" }\n" -"\n" -" float side = float(arc_list.side);\n" -" float min_dist = GLYPHY_INFINITY;\n" -" glyphy_arc_t closest_arc;\n" -"\n" -" glyphy_arc_endpoint_t endpoint_prev, endpoint;\n" -" endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size);\n" -" for (int i = 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++)\n" -" {\n" -" if (i >= arc_list.num_endpoints) {\n" -" break;\n" -" }\n" -" endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size);\n" -" glyphy_arc_t a = glyphy_arc_t (endpoint_prev.p, endpoint.p, endpoint.d);\n" -" endpoint_prev = endpoint;\n" -" if (glyphy_isinf (a.d)) continue;\n" -"\n" -" if (glyphy_arc_wedge_contains (a, p))\n" -" {\n" -" float sdist = glyphy_arc_wedge_signed_dist (a, p);\n" -" float udist = abs (sdist) * (1. - GLYPHY_EPSILON);\n" -" if (udist <= min_dist) {\n" -" min_dist = udist;\n" -" side = sdist <= 0. ? -1. : +1.;\n" -" }\n" -" } else {\n" -" float udist = min (distance (p, a.p0), distance (p, a.p1));\n" -" if (udist < min_dist) {\n" -" min_dist = udist;\n" -" side = 0.; /* unsure */\n" -" closest_arc = a;\n" -" } else if (side == 0. && udist == min_dist) {\n" -" /* If this new distance is the same as the current minimum,\n" -" * compare extended distances. Take the sign from the arc\n" -" * with larger extended distance. */\n" -" float old_ext_dist = glyphy_arc_extended_dist (closest_arc, p);\n" -" float new_ext_dist = glyphy_arc_extended_dist (a, p);\n" -"\n" -" float ext_dist = abs (new_ext_dist) <= abs (old_ext_dist) ?\n" -" old_ext_dist : new_ext_dist;\n" -"\n" -"#ifdef GLYPHY_SDF_PSEUDO_DISTANCE\n" -" /* For emboldening and stuff: */\n" -" min_dist = abs (ext_dist);\n" -"#endif\n" -" side = sign (ext_dist);\n" -" }\n" -" }\n" -" }\n" -"\n" -" if (side == 0.) {\n" -" // Technically speaking this should not happen, but it does. So try to fix it.\n" -" float ext_dist = glyphy_arc_extended_dist (closest_arc, p);\n" -" side = sign (ext_dist);\n" -" }\n" -"\n" -" return min_dist * side;\n" -"}\n" -"\n" -"float\n" -"glyphy_point_dist (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)\n" -"{\n" -" glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS);\n" -"\n" -" float side = float(arc_list.side);\n" -" float min_dist = GLYPHY_INFINITY;\n" -"\n" -" if (arc_list.num_endpoints == 0)\n" -" return min_dist;\n" -"\n" -" glyphy_arc_endpoint_t endpoint;\n" -" for (int i = 0; i < GLYPHY_MAX_NUM_ENDPOINTS; i++)\n" -" {\n" -" if (i >= arc_list.num_endpoints) {\n" -" break;\n" -" }\n" -" endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size);\n" -" if (glyphy_isinf (endpoint.d)) continue;\n" -" min_dist = min (min_dist, distance (p, endpoint.p));\n" -" }\n" -" return min_dist;\n" -"}\n" -; diff --git a/src/glyphy/glyphy-sdf.glsl b/src/glyphy/glyphy-sdf.glsl @@ -0,0 +1,150 @@ +/* + * Copyright 2012 Google, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Google Author(s): Behdad Esfahbod, Maysum Panju + */ + +#ifndef GLYPHY_TEXTURE1D_FUNC +#define GLYPHY_TEXTURE1D_FUNC glyphy_texture1D_func +#endif +#ifndef GLYPHY_TEXTURE1D_EXTRA_DECLS +#define GLYPHY_TEXTURE1D_EXTRA_DECLS +#endif +#ifndef GLYPHY_TEXTURE1D_EXTRA_ARGS +#define GLYPHY_TEXTURE1D_EXTRA_ARGS +#endif + +#ifndef GLYPHY_SDF_TEXTURE1D_FUNC +#define GLYPHY_SDF_TEXTURE1D_FUNC GLYPHY_TEXTURE1D_FUNC +#endif +#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS +#define GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS GLYPHY_TEXTURE1D_EXTRA_DECLS +#endif +#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS +#define GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS GLYPHY_TEXTURE1D_EXTRA_ARGS +#endif +#ifndef GLYPHY_SDF_TEXTURE1D +#define GLYPHY_SDF_TEXTURE1D(offset) GLYPHY_RGBA(GLYPHY_SDF_TEXTURE1D_FUNC (offset GLYPHY_TEXTURE1D_EXTRA_ARGS)) +#endif + +#ifndef GLYPHY_MAX_NUM_ENDPOINTS +#define GLYPHY_MAX_NUM_ENDPOINTS 32 +#endif + +glyphy_arc_list_t +glyphy_arc_list (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) +{ + int cell_offset = glyphy_arc_list_offset (p, nominal_size); + vec4 arc_list_data = GLYPHY_SDF_TEXTURE1D (cell_offset); + return glyphy_arc_list_decode (arc_list_data, nominal_size); +} + +float +glyphy_sdf (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) +{ + glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); + + /* Short-circuits */ + if (arc_list.num_endpoints == 0) { + /* far-away cell */ + return GLYPHY_INFINITY * float(arc_list.side); + } if (arc_list.num_endpoints == -1) { + /* single-line */ + float angle = arc_list.line_angle; + vec2 n = vec2 (cos (angle), sin (angle)); + return dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance; + } + + float side = float(arc_list.side); + float min_dist = GLYPHY_INFINITY; + glyphy_arc_t closest_arc; + + glyphy_arc_endpoint_t endpoint_prev, endpoint; + endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size); + for (int i = 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) + { + if (i >= arc_list.num_endpoints) { + break; + } + endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size); + glyphy_arc_t a = glyphy_arc_t (endpoint_prev.p, endpoint.p, endpoint.d); + endpoint_prev = endpoint; + if (glyphy_isinf (a.d)) continue; + + if (glyphy_arc_wedge_contains (a, p)) + { + float sdist = glyphy_arc_wedge_signed_dist (a, p); + float udist = abs (sdist) * (1. - GLYPHY_EPSILON); + if (udist <= min_dist) { + min_dist = udist; + side = sdist <= 0. ? -1. : +1.; + } + } else { + float udist = min (distance (p, a.p0), distance (p, a.p1)); + if (udist < min_dist) { + min_dist = udist; + side = 0.; /* unsure */ + closest_arc = a; + } else if (side == 0. && udist == min_dist) { + /* If this new distance is the same as the current minimum, + * compare extended distances. Take the sign from the arc + * with larger extended distance. */ + float old_ext_dist = glyphy_arc_extended_dist (closest_arc, p); + float new_ext_dist = glyphy_arc_extended_dist (a, p); + + float ext_dist = abs (new_ext_dist) <= abs (old_ext_dist) ? + old_ext_dist : new_ext_dist; + +#ifdef GLYPHY_SDF_PSEUDO_DISTANCE + /* For emboldening and stuff: */ + min_dist = abs (ext_dist); +#endif + side = sign (ext_dist); + } + } + } + + if (side == 0.) { + // Technically speaking this should not happen, but it does. So try to fix it. + float ext_dist = glyphy_arc_extended_dist (closest_arc, p); + side = sign (ext_dist); + } + + return min_dist * side; +} + +float +glyphy_point_dist (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) +{ + glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); + + float side = float(arc_list.side); + float min_dist = GLYPHY_INFINITY; + + if (arc_list.num_endpoints == 0) + return min_dist; + + glyphy_arc_endpoint_t endpoint; + for (int i = 0; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) + { + if (i >= arc_list.num_endpoints) { + break; + } + endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size); + if (glyphy_isinf (endpoint.d)) continue; + min_dist = min (min_dist, distance (p, endpoint.p)); + } + return min_dist; +} diff --git a/src/glyphy/glyphy-shaders.cc b/src/glyphy/glyphy-shaders.cc @@ -29,8 +29,8 @@ /* TODO path separator */ #define SHADER_PATH(File) PKGDATADIR "/" File -#include "glyphy-common-glsl.h" -#include "glyphy-sdf-glsl.h" +#include "glyphy_common_glsl.h" +#include "glyphy_sdf_glsl.h" const char * glyphy_common_shader_source (void) { return glyphy_common_glsl; } const char * glyphy_sdf_shader_source (void) { return glyphy_sdf_glsl; } diff --git a/src/stringize b/src/stringize @@ -0,0 +1,17 @@ +#!/bin/sh + +if test "$#" = 0; then + echo "Usage: $0 DECL-SPEC FILE..." + exit 1 +fi +decl="$1" +shift + +echo "$decl =" +sed ' +s/\\/\\\\/g; +s/"/\\"/g; +s/^/"/; +s/$/\\n"/; +' "$@" +echo ";"