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:
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);