vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

Commit: fd7b64ba4fdc4eb9f71d7eb5c5a21dae7be88084
Parent: e1a0ef1a8155f75a57aa301b52ed1f77396c7055
Author: Randy Palamar
Date:   Tue,  3 Sep 2024 22:07:22 -0600

stb_truetype: first pass at malloc removal

This removes all users in our path of malloc/free. Even the
garbage stbtt__hheap_alloc can be ignored by making sure our entry
point takes an Arena and not an Arena *.

Diffstat:
Mbuild.sh | 3+++
Mextern/stb_truetype.h | 229++++++++++++++++++++++---------------------------------------------------------
Mfont.c | 12+++++-------
Mvtgl.c | 39++++++++++++++++++++-------------------
4 files changed, 92 insertions(+), 191 deletions(-)

diff --git a/build.sh b/build.sh @@ -20,6 +20,9 @@ if [ $debug ]; then cflags="$cflags -D_DEBUG -Wno-unused-function -Wno-undefined-internal" #cflags="$cflags -fsanitize=address,undefined" + # NOTE: determine which stb_truetype functions are calling malloc/free + #cflags="$cflags -DTRACK_MALLOC" + libcflags="$cflags -ggdb -O0 -fPIC" libldflags="$ldflags -shared" diff --git a/extern/stb_truetype.h b/extern/stb_truetype.h @@ -118,7 +118,6 @@ // stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections // // Render a unicode codepoint to a bitmap -// stbtt_GetGlyphBitmap() -- allocates and returns a bitmap // stbtt_MakeGlyphBitmap() -- renders into bitmap you provide // stbtt_GetGlyphBitmapBox() -- how big the bitmap must be // @@ -377,7 +376,7 @@ typedef struct float xoff,yoff,xadvance; } stbtt_bakedchar; -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) +STBTT_DEF int stbtt_BakeFontBitmap(Arena a, const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) float pixel_height, // height of font in pixels unsigned char *pixels, int pw, int ph, // bitmap to be filled in int first_char, int num_chars, // characters to bake @@ -448,8 +447,9 @@ STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); #define STBTT_POINT_SIZE(x) (-(x)) -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, - int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); +STBTT_DEF int stbtt_PackFontRange(Arena a, stbtt_pack_context *spc, const unsigned char *fontdata, + int font_index, float font_size, int first_unicode_char_in_range, + int num_chars_in_range, stbtt_packedchar *chardata_for_range); // Creates character bitmaps from the font_index'th font found in fontdata (use // font_index=0 if you don't know what that is). It creates num_chars_in_range // bitmaps for characters with unicode values starting at first_unicode_char_in_range @@ -473,7 +473,8 @@ typedef struct unsigned char h_oversample, v_oversample; // don't set these, they're used internally } stbtt_pack_range; -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +STBTT_DEF int stbtt_PackFontRanges(Arena a, stbtt_pack_context *spc, const unsigned char *fontdata, + int font_index, stbtt_pack_range *ranges, int num_ranges); // Creates character bitmaps from multiple ranges of characters stored in // ranges. This will usually create a better-packed bitmap than multiple // calls to stbtt_PackFontRange. Note that you can call this multiple @@ -509,7 +510,7 @@ STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(Arena a, stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); // Calling these functions in sequence is roughly equivalent to calling // stbtt_PackFontRanges(). If you more control over the packing of multiple // fonts, or if you want to pack custom data into a font texture, take a look @@ -684,7 +685,8 @@ STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningen STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); // returns non-zero if nothing is drawn for this glyph -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); +STBTT_DEF int stbtt_GetGlyphShape(Arena *a, const stbtt_fontinfo *info, int glyph_index, + stbtt_vertex **vertices); // returns # of vertices and fills *vertices with the pointer to them // these are expressed in "unscaled" coordinates // @@ -708,42 +710,25 @@ STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char * // BITMAP RENDERING // -STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); -// frees the bitmap allocated below - -STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, - float scale_y, int glyph, int *width, int *height, - int *xoff, int *yoff); -// allocates a large-enough single-channel 8bpp bitmap and renders the -// specified character/glyph at the specified scale into it, with +STBTT_DEF void stbtt_MakeGlyphBitmap(Arena a, const stbtt_fontinfo *info, unsigned char *output, int out_w, + int out_h, int out_stride, float scale_x, float scale_y, int glyph); +// renders a single-channel 8bpp bitmap glyph into output at the specified scale, with // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). // *width & *height are filled out with the width & height of the bitmap, // which is stored left-to-right, top-to-bottom. -// -// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap - -STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, - float scale_y, float shift_x, float shift_y, - int glyph, int *width, int *height, - int *xoff, int *yoff); -// the same as stbtt_GetGlyphBitmap, but you can specify a subpixel shift for the character - -STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, - int out_h, int out_stride, float scale_x, float scale_y, int glyph); -// the same as stbtt_GetGlyphBitmap, but you pass in storage for the bitmap -// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap +// output has row spacing of 'out_stride' bytes. the bitmap // is clipped to out_w/out_h bytes. Call stbtt_GetGlyphBitmapBox to get the // width and height and positioning info for it first. -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(Arena a, const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); // same as stbtt_MakeGlyphBitmap, but you can specify a subpixel shift for the character -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, - int out_w, int out_h, int out_stride, - float scale_x, float scale_y, float shift_x, - float shift_y, int oversample_x, +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(Arena a, const stbtt_fontinfo *info, + unsigned char *output, int out_w, int out_h, + int out_stride, float scale_x, float scale_y, + float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); // same as stbtt_MakeGlyphBitmapSubpixel, but prefiltering is performed (see stbtt_PackSetOversampling) @@ -770,7 +755,7 @@ typedef struct } stbtt__bitmap; // rasterize a shape with quadratic beziers into a bitmap -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into +STBTT_DEF void stbtt_Rasterize(Arena a, stbtt__bitmap *result, // 1-channel bitmap to draw into float flatness_in_pixels, // allowable error of curve in pixels stbtt_vertex *vertices, // array of vertices defining shape int num_verts, // number of vertices in above array @@ -787,7 +772,10 @@ STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); // frees the SDF bitmap allocated below -STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(Arena *a, const stbtt_fontinfo *info, float scale, + int glyph, int padding, unsigned char onedge_value, + float pixel_dist_scale, int *width, int *height, + int *xoff, int *yoff); // These functions compute a discretized SDF field for a single character, suitable for storing // in a single-channel texture, sampling with bilinear filtering, and testing against // larger than some threshold to produce scalable fonts. @@ -1498,7 +1486,7 @@ static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_ return num_vertices; } -static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +static int stbtt__GetGlyphShapeTT(Arena *a, const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { stbtt_int16 numberOfContours; stbtt_uint8 *endPtsOfContours; @@ -1525,9 +1513,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); m = n + 2*numberOfContours; // a loose bound on how many vertices we might need - vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); - if (vertices == 0) - return 0; + vertices = alloc(a, typeof(*vertices), m); next_move = 0; flagcount=0; @@ -1683,7 +1669,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); // Get indexed glyph. - comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + comp_num_verts = stbtt_GetGlyphShape(a, info, gidx, &comp_verts); if (comp_num_verts > 0) { // Transform vertices. for (i = 0; i < comp_num_verts; ++i) { @@ -2121,10 +2107,10 @@ static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, in return r ? c.num_vertices : 0; } -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +STBTT_DEF int stbtt_GetGlyphShape(Arena *a, const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { if (!info->cff.size) - return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + return stbtt__GetGlyphShapeTT(a, info, glyph_index, pvertices); else return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); } @@ -2567,7 +2553,7 @@ typedef struct stbtt__hheap int num_remaining_in_head_chunk; } stbtt__hheap; -static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) +static void *stbtt__hheap_alloc(Arena *a, stbtt__hheap *hh, size_t size) { if (hh->first_free) { void *p = hh->first_free; @@ -2576,7 +2562,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) } else { if (hh->num_remaining_in_head_chunk == 0) { int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); - stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + stbtt__hheap_chunk *c = alloc_(a, sizeof(stbtt__hheap_chunk) + size * count, _Alignof(stbtt__hheap_chunk), 1); if (c == NULL) return NULL; c->next = hh->head; @@ -2594,16 +2580,6 @@ static void stbtt__hheap_free(stbtt__hheap *hh, void *p) hh->first_free = p; } -static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) -{ - stbtt__hheap_chunk *c = hh->head; - while (c) { - stbtt__hheap_chunk *n = c->next; - STBTT_free(c, userdata); - c = n; - } -} - typedef struct stbtt__edge { float x0,y0, x1,y1; int invert; @@ -2654,9 +2630,9 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i return z; } #elif STBTT_RASTERIZER_VERSION == 2 -static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +static stbtt__active_edge *stbtt__new_active(Arena *a, stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point) { - stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(a, hh, sizeof(*z)); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); STBTT_assert(z != NULL); //STBTT_assert(e->y0 <= start_point); @@ -2815,8 +2791,6 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, ++j; } - stbtt__hheap_cleanup(&hh, userdata); - if (scanline != scanline_data) STBTT_free(scanline, userdata); } @@ -3094,7 +3068,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, } // directly AA rasterize edges w/o supersampling -static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +static void stbtt__rasterize_sorted_edges(Arena *a, stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) { stbtt__hheap hh = { 0, 0, 0 }; stbtt__active_edge *active = NULL; @@ -3139,7 +3113,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, // insert all edges that start before the bottom of this scanline while (e->y0 <= scan_y_bottom) { if (e->y0 != e->y1) { - stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + stbtt__active_edge *z = stbtt__new_active(a, &hh, e, off_x, scan_y_top); if (z != NULL) { if (j == 0 && off_y != 0) { if (z->ey < scan_y_top) { @@ -3185,8 +3159,6 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, ++j; } - stbtt__hheap_cleanup(&hh, userdata); - if (scanline != scanline_data) STBTT_free(scanline, userdata); } @@ -3282,12 +3254,9 @@ static void stbtt__sort_edges(stbtt__edge *p, int n) stbtt__sort_edges_ins_sort(p, n); } -typedef struct -{ - float x,y; -} stbtt__point; +typedef v2 stbtt__point; -static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +static void stbtt__rasterize(Arena *a, stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) { float y_scale_inv = invert ? -scale_y : scale_y; stbtt__edge *e; @@ -3306,8 +3275,7 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou for (i=0; i < windings; ++i) n += wcount[i]; - e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel - if (e == 0) return; + e = alloc(a, typeof(*e), n + 1); // add an extra one as a sentinel n = 0; m=0; @@ -3339,9 +3307,7 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou stbtt__sort_edges(e, n); // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule - stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); - - STBTT_free(e, userdata); + stbtt__rasterize_sorted_edges(a, result, e, n, vsubsample, off_x, off_y, userdata); } static void stbtt__add_point(stbtt__point *points, int n, float x, float y) @@ -3415,7 +3381,7 @@ static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float } // returns number of contours -static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +static stbtt__point *stbtt_FlattenCurves(Arena *a, stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) { stbtt__point *points=0; int num_points=0; @@ -3431,19 +3397,13 @@ static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, *num_contours = n; if (n == 0) return 0; - *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); - - if (*contour_lengths == 0) { - *num_contours = 0; - return 0; - } + *contour_lengths = alloc(a, typeof(**contour_lengths), n); // make two passes through the points so we don't need to realloc for (pass=0; pass < 2; ++pass) { float x=0,y=0; if (pass == 1) { - points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); - if (points == NULL) goto error; + points = alloc(a, typeof(*points), num_points); } num_points = 0; n= -1; @@ -3484,82 +3444,23 @@ static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, } return points; -error: - STBTT_free(points, userdata); - STBTT_free(*contour_lengths, userdata); - *contour_lengths = 0; - *num_contours = 0; - return NULL; } -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +STBTT_DEF void stbtt_Rasterize(Arena a, stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { float scale = scale_x > scale_y ? scale_y : scale_x; int winding_count = 0; int *winding_lengths = NULL; - stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); - if (windings) { - stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); - STBTT_free(winding_lengths, userdata); - STBTT_free(windings, userdata); - } -} - -STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) -{ - STBTT_free(bitmap, userdata); + stbtt__point *windings = stbtt_FlattenCurves(&a, vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) + stbtt__rasterize(&a, result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); } -STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) -{ - int ix0,iy0,ix1,iy1; - stbtt__bitmap gbm; - stbtt_vertex *vertices; - int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - - if (scale_x == 0) scale_x = scale_y; - if (scale_y == 0) { - if (scale_x == 0) { - STBTT_free(vertices, info->userdata); - return NULL; - } - scale_y = scale_x; - } - - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); - - // now we get the size - gbm.w = (ix1 - ix0); - gbm.h = (iy1 - iy0); - gbm.pixels = NULL; // in case we error - - if (width ) *width = gbm.w; - if (height) *height = gbm.h; - if (xoff ) *xoff = ix0; - if (yoff ) *yoff = iy0; - - if (gbm.w && gbm.h) { - gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); - if (gbm.pixels) { - gbm.stride = gbm.w; - - stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); - } - } - STBTT_free(vertices, info->userdata); - return gbm.pixels; -} - -STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); -} - -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(Arena a, const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) { int ix0,iy0; stbtt_vertex *vertices; - int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + int num_verts = stbtt_GetGlyphShape(&a, info, glyph, &vertices); stbtt__bitmap gbm; stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); @@ -3569,14 +3470,12 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigne gbm.stride = out_stride; if (gbm.w && gbm.h) - stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); - - STBTT_free(vertices, info->userdata); + stbtt_Rasterize(a, &gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); } -STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +STBTT_DEF void stbtt_MakeGlyphBitmap(Arena a, const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) { - stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); + stbtt_MakeGlyphBitmapSubpixel(a, info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); } ////////////////////////////////////////////////////////////////////////////// @@ -3585,7 +3484,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char * // // This is SUPER-CRAPPY packing to keep source code small -static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) +static int stbtt_BakeFontBitmap_internal(Arena a, unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) float pixel_height, // height of font in pixels unsigned char *pixels, int pw, int ph, // bitmap to be filled in int first_char, int num_chars, // characters to bake @@ -3616,7 +3515,7 @@ static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // fo return -i; STBTT_assert(x+gw < pw); STBTT_assert(y+gh < ph); - stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + stbtt_MakeGlyphBitmap(a, &f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); chardata[i].x0 = (stbtt_int16) x; chardata[i].y0 = (stbtt_int16) y; chardata[i].x1 = (stbtt_int16) (x + gw); @@ -3956,9 +3855,9 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb return k; } -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(Arena a, const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) { - stbtt_MakeGlyphBitmapSubpixel(info, + stbtt_MakeGlyphBitmapSubpixel(a, info, output, out_w - (prefilter_x - 1), out_h - (prefilter_y - 1), @@ -3980,7 +3879,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info } // rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(Arena a, stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { int i,j,k, missing_glyph = -1, return_value = 1; @@ -4018,7 +3917,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const scale * spc->h_oversample, scale * spc->v_oversample, &x0,&y0,&x1,&y1); - stbtt_MakeGlyphBitmapSubpixel(info, + stbtt_MakeGlyphBitmapSubpixel(a, info, spc->pixels + r->x + r->y*spc->stride_in_bytes, r->w - spc->h_oversample+1, r->h - spc->v_oversample+1, @@ -4074,7 +3973,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); } -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +STBTT_DEF int stbtt_PackFontRanges(Arena a, stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) { stbtt_fontinfo info; int i,j,n, return_value = 1; @@ -4104,13 +4003,13 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char stbtt_PackFontRangesPackRects(spc, rects, n); - return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + return_value = stbtt_PackFontRangesRenderIntoRects(a, spc, &info, ranges, num_ranges, rects); STBTT_free(rects, spc->user_allocator_context); return return_value; } -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(Arena a, stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) { stbtt_pack_range range; @@ -4119,7 +4018,7 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char * range.num_chars = num_chars_in_range; range.chardata_for_range = chardata_for_range; range.font_size = font_size; - return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); + return stbtt_PackFontRanges(a, spc, fontdata, font_index, &range, 1); } STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) @@ -4347,7 +4246,7 @@ static int stbtt__solve_cubic(float a, float b, float c, float* r) } } -STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char *stbtt_GetGlyphSDF(Arena *a, const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) { float scale_x = scale, scale_y = scale; int ix0,iy0,ix1,iy1; @@ -4384,7 +4283,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc int x,y,i,j; float *precompute; stbtt_vertex *verts; - int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + int num_verts = stbtt_GetGlyphShape(a, info, glyph, &verts); data = (unsigned char *) STBTT_malloc(w * h, info->userdata); precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); @@ -4704,11 +4603,11 @@ static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char #pragma GCC diagnostic ignored "-Wcast-qual" #endif -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, +STBTT_DEF int stbtt_BakeFontBitmap(Arena a, const unsigned char *data, int offset, float pixel_height, unsigned char *pixels, int pw, int ph, int first_char, int num_chars, stbtt_bakedchar *chardata) { - return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); + return stbtt_BakeFontBitmap_internal(a, (unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); } STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) diff --git a/font.c b/font.c @@ -119,11 +119,8 @@ get_and_clear_glyph_cache_stats(GlyphCache *gc) return result; } -static u32 glyph_buf[MAX_FONT_SIZE * MAX_FONT_SIZE * sizeof(u32)]; -static u8 temp_buf[MAX_FONT_SIZE * MAX_FONT_SIZE * sizeof(u8)]; - static u32 * -render_glyph(FontAtlas *fa, u32 cp, enum face_style style, CachedGlyph **out_glyph, u32 *out_idx) +render_glyph(Arena *a, FontAtlas *fa, u32 cp, enum face_style style, CachedGlyph **out_glyph, u32 *out_idx) { /* NOTE: first check if glyph is in the cache and valid */ /* NOTE: 8 MSB are not used for UTF8 so we can use that to store the style of the glyph */ @@ -160,17 +157,18 @@ render_glyph(FontAtlas *fa, u32 cp, enum face_style style, CachedGlyph **out_gly cg->g.delta.x = x0; cg->g.delta.y = -y1; - stbtt_MakeGlyphBitmapSubpixel(&f->font_info, temp_buf, cg->g.size.w, cg->g.size.h, + u8 *render_buf = alloc(a, u8, cg->g.size.w * cg->g.size.h); + stbtt_MakeGlyphBitmapSubpixel(*a, &f->font_info, render_buf, cg->g.size.w, cg->g.size.h, cg->g.size.w, scale, scale, 0, 0, glyph_idx); - u32 *rgba_bitmap = mem_clear((u8 *)glyph_buf, 0, sizeof(glyph_buf)); + u32 *rgba_bitmap = alloc(a, u32, cg->g.size.w * cg->g.size.h); for (u32 i = 0; i < cg->g.size.h; i++) { for (u32 j = 0; j < cg->g.size.w; j++) { /* TODO: handled coloured glyphs */ u32 pixel = 0; if (0 /* COLOURED */) { } else { - pixel = (u32)(temp_buf[i * cg->g.size.w + j]) << 24; + pixel = (u32)(render_buf[i * cg->g.size.w + j]) << 24; } rgba_bitmap[i * cg->g.size.w + j] = pixel; } diff --git a/vtgl.c b/vtgl.c @@ -172,11 +172,11 @@ update_uniforms(Term *t, enum shader_stages stage) } static i32 -get_gpu_glyph_index(FontAtlas *fa, u32 codepoint, enum face_style style, Glyph *out_glyph) +get_gpu_glyph_index(Arena a, FontAtlas *fa, u32 codepoint, enum face_style style, Glyph *out_glyph) { u32 depth_idx; CachedGlyph *cg; - u32 *data = render_glyph(fa, codepoint, style, &cg, &depth_idx); + u32 *data = render_glyph(&a, fa, codepoint, style, &cg, &depth_idx); *out_glyph = cg->g; if (data) { ASSERT(depth_idx); @@ -190,14 +190,14 @@ get_gpu_glyph_index(FontAtlas *fa, u32 codepoint, enum face_style style, Glyph * } static v2 -measure_text(FontAtlas *fa, s8 text, b32 monospaced) +measure_text(Arena a, FontAtlas *fa, s8 text, b32 monospaced) { v2 result = {0}; Glyph g; - get_gpu_glyph_index(fa, ' ', FS_NORMAL, &g); + get_gpu_glyph_index(a, fa, ' ', FS_NORMAL, &g); f32 single_space_width = g.size.w; for (size i = 0; i < text.len; i++) { - get_gpu_glyph_index(fa, text.data[i], FS_NORMAL, &g); + get_gpu_glyph_index(a, fa, text.data[i], FS_NORMAL, &g); /* TODO: should we consider offset characters in y? */ if (g.size.h > result.y) result.y = g.size.h; @@ -255,14 +255,14 @@ push_empty_cell_rect(RenderPushBuffer *rpb, Term *t, u32 minrow, u32 maxrow, u32 } static void -draw_text(RenderPushBuffer *rpb, GLCtx *gl, FontAtlas *fa, s8 text, v2 position, Colour colour, b32 monospaced) +draw_text(RenderPushBuffer *rpb, GLCtx *gl, Arena a, FontAtlas *fa, s8 text, v2 position, Colour colour, b32 monospaced) { Glyph g; - get_gpu_glyph_index(fa, ' ', FS_NORMAL, &g); + get_gpu_glyph_index(a, fa, ' ', FS_NORMAL, &g); f32 single_space_width = g.size.w; for (size i = 0; i < text.len; i++) { u32 cp = text.data[i]; - i32 glyph_idx = get_gpu_glyph_index(fa, cp, FS_NORMAL, &g); + i32 glyph_idx = get_gpu_glyph_index(a, fa, cp, FS_NORMAL, &g); v2 texscale = {.x = g.size.w / MAX_FONT_SIZE, .y = g.size.h / MAX_FONT_SIZE}; v2 vertscale = {.x = g.size.w, .y = g.size.h}; v2 vertoff = {.x = position.x + g.delta.x, .y = position.y + g.delta.y}; @@ -278,7 +278,7 @@ draw_rectangle(RenderPushBuffer *rpb, GLCtx *gl, Rect r, Colour colour) } static void -push_cell(RenderPushBuffer *rpb, GLCtx *gl, FontAtlas *fa, Cell c, Rect r, v2 cell_font_delta) +push_cell(RenderPushBuffer *rpb, GLCtx *gl, Arena a, FontAtlas *fa, Cell c, Rect r, v2 cell_font_delta) { u32 idx = get_render_push_buffer_idx(rpb, gl, 2); @@ -293,7 +293,7 @@ push_cell(RenderPushBuffer *rpb, GLCtx *gl, FontAtlas *fa, Cell c, Rect r, v2 ce else if (c.style.attr & ATTR_ITALIC) style = FS_ITALIC; - i32 depth_idx = get_gpu_glyph_index(fa, c.cp, style, &g); + i32 depth_idx = get_gpu_glyph_index(a, fa, c.cp, style, &g); rpb->vertscales[idx + 0] = r.size; rpb->vertscales[idx + 1] = (v2){.x = g.size.w, .y = g.size.h}; @@ -330,8 +330,8 @@ push_cell(RenderPushBuffer *rpb, GLCtx *gl, FontAtlas *fa, Cell c, Rect r, v2 ce } static void -push_cell_row(RenderPushBuffer *rpb, GLCtx *gl, FontAtlas *fa, Cell *row, u32 len, b32 inverse, - Rect cr, v2 cell_font_delta) +push_cell_row(RenderPushBuffer *rpb, GLCtx *gl, Arena a, FontAtlas *fa, Cell *row, u32 len, + b32 inverse, Rect cr, v2 cell_font_delta) { ASSERT(inverse == 0 || inverse == 1); v2 cs = cr.size; @@ -343,7 +343,7 @@ push_cell_row(RenderPushBuffer *rpb, GLCtx *gl, FontAtlas *fa, Cell *row, u32 le if (cell.style.attr & ATTR_WIDE) cr.size = csw; else cr.size = cs; cell.style.attr ^= inverse * ATTR_INVERSE; - push_cell(rpb, gl, fa, cell, cr, cell_font_delta); + push_cell(rpb, gl, a, fa, cell, cr, cell_font_delta); cr.pos.x += cr.size.w; } } @@ -365,7 +365,7 @@ render_framebuffer(Term *t, RenderPushBuffer *rpb) TermView *tv = t->views + t->view_idx; /* NOTE: draw whole framebuffer */ for (u32 r = 0; r < t->size.h; r++) { - push_cell_row(rpb, &t->gl, &t->fa, tv->fb.rows[r], t->size.w, 0, + push_cell_row(rpb, &t->gl, t->arena_for_frame, &t->fa, tv->fb.rows[r], t->size.w, 0, cr, cell_font_delta); cr.pos.y -= cs.h; } @@ -380,14 +380,14 @@ render_framebuffer(Term *t, RenderPushBuffer *rpb) /* NOTE: do full rows first */ for (; curs.y < end.y; curs.y++) { u32 len = t->size.w - curs.x - 1; - push_cell_row(rpb, &t->gl, &t->fa, tv->fb.rows[curs.y] + curs.x, len, 1, + push_cell_row(rpb, &t->gl, t->arena_for_frame, &t->fa, tv->fb.rows[curs.y] + curs.x, len, 1, cr, cell_font_delta); curs.x = 0; cr.pos.x = tl.x; cr.pos.y -= cs.h; } /* NOTE: do the last row */ - push_cell_row(rpb, &t->gl, &t->fa, tv->fb.rows[curs.y] + curs.x, + push_cell_row(rpb, &t->gl, t->arena_for_frame, &t->fa, tv->fb.rows[curs.y] + curs.x, end.x - curs.x + 1, 1, cr, cell_font_delta); } @@ -403,7 +403,7 @@ render_framebuffer(Term *t, RenderPushBuffer *rpb) if (cursor.style.attr & ATTR_WIDE) cr.size.w *= 2; cursor.style.attr ^= ATTR_INVERSE; - push_cell(rpb, &t->gl, &t->fa, cursor, cr, cell_font_delta); + push_cell(rpb, &t->gl, t->arena_for_frame, &t->fa, cursor, cr, cell_font_delta); } } @@ -860,7 +860,7 @@ do_terminal(Term *t) s8 fps = s8alloc(&t->arena_for_frame, 64); fps.len = snprintf((char *)fps.data, fps.len, "Render Time: %0.02f ms/f", last_frame_time * 1e3); - v2 ts = measure_text(&t->fa, fps, 1); + v2 ts = measure_text(t->arena_for_frame, &t->fa, fps, 1); v2 pos = {.x = ws.w - ts.x - 10, .y = src_tr.y - ts.y - 10}; Rect r = { @@ -869,7 +869,8 @@ do_terminal(Term *t) }; draw_rectangle(rpb, &t->gl, r, (Colour){.rgba = 0x303030ff}); - draw_text(rpb, &t->gl, &t->fa, fps, pos, (Colour){.rgba = 0x1e9e33ff}, 1); + draw_text(rpb, &t->gl, t->arena_for_frame, &t->fa, fps, pos, + (Colour){.rgba = 0x1e9e33ff}, 1); } flush_render_push_buffer(rpb, &t->gl);