|
@@ -105,7 +105,7 @@
|
|
// #include "stb_rect_pack.h" -- optional, but you really want it
|
|
// #include "stb_rect_pack.h" -- optional, but you really want it
|
|
// stbtt_PackBegin()
|
|
// stbtt_PackBegin()
|
|
// stbtt_PackSetOversample() -- for improved quality on small fonts
|
|
// stbtt_PackSetOversample() -- for improved quality on small fonts
|
|
-// stbtt_PackFontRanges()
|
|
|
|
|
|
+// stbtt_PackFontRanges() -- pack and renders
|
|
// stbtt_PackEnd()
|
|
// stbtt_PackEnd()
|
|
// stbtt_GetPackedQuad()
|
|
// stbtt_GetPackedQuad()
|
|
//
|
|
//
|
|
@@ -525,6 +525,10 @@ typedef struct
|
|
} stbtt_packedchar;
|
|
} stbtt_packedchar;
|
|
|
|
|
|
typedef struct stbtt_pack_context stbtt_pack_context;
|
|
typedef struct stbtt_pack_context stbtt_pack_context;
|
|
|
|
+typedef struct stbtt_fontinfo stbtt_fontinfo;
|
|
|
|
+#ifndef STB_RECT_PACK_VERSION
|
|
|
|
+typedef struct stbrp_rect stbrp_rect;
|
|
|
|
+#endif
|
|
|
|
|
|
STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
|
|
STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
|
|
// Initializes a packing context stored in the passed-in stbtt_pack_context.
|
|
// Initializes a packing context stored in the passed-in stbtt_pack_context.
|
|
@@ -570,6 +574,12 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *font
|
|
// ranges. This will usually create a better-packed bitmap than multiple
|
|
// ranges. This will usually create a better-packed bitmap than multiple
|
|
// calls to stbtt_PackFontRange.
|
|
// calls to stbtt_PackFontRange.
|
|
|
|
|
|
|
|
+STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
|
|
|
|
+STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
|
|
|
|
+// Those functions are called by stbtt_PackFontRanges(). If you want to
|
|
|
|
+// pack multiple fonts or custom data into a same texture, you may copy
|
|
|
|
+// the contents of stbtt_PackFontRanges() and create a custom version
|
|
|
|
+// using those functions.
|
|
|
|
|
|
STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
|
|
STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
|
|
// Oversampling a font increases the quality by allowing higher-quality subpixel
|
|
// Oversampling a font increases the quality by allowing higher-quality subpixel
|
|
@@ -2572,11 +2582,11 @@ typedef struct
|
|
unsigned char x;
|
|
unsigned char x;
|
|
} stbrp_node;
|
|
} stbrp_node;
|
|
|
|
|
|
-typedef struct
|
|
|
|
|
|
+struct stbrp_rect
|
|
{
|
|
{
|
|
stbrp_coord x,y;
|
|
stbrp_coord x,y;
|
|
int id,w,h,was_packed;
|
|
int id,w,h,was_packed;
|
|
-} stbrp_rect;
|
|
|
|
|
|
+};
|
|
|
|
|
|
static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
|
|
static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
|
|
{
|
|
{
|
|
@@ -2643,7 +2653,8 @@ STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, in
|
|
|
|
|
|
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
|
|
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
|
|
|
|
|
|
- STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
|
|
|
|
|
|
+ if (pixels)
|
|
|
|
+ STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -2786,63 +2797,51 @@ static float stbtt__oversample_shift(int oversample)
|
|
return (float)-(oversample - 1) / (2.0f * (float)oversample);
|
|
return (float)-(oversample - 1) / (2.0f * (float)oversample);
|
|
}
|
|
}
|
|
|
|
|
|
-STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
|
|
|
|
|
|
+// rects array must be big enough to accommodate all characters in the given ranges
|
|
|
|
+STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
|
{
|
|
{
|
|
- stbtt_fontinfo info;
|
|
|
|
- float recip_h = 1.0f / spc->h_oversample;
|
|
|
|
- float recip_v = 1.0f / spc->v_oversample;
|
|
|
|
- float sub_x = stbtt__oversample_shift(spc->h_oversample);
|
|
|
|
- float sub_y = stbtt__oversample_shift(spc->v_oversample);
|
|
|
|
- int i,j,k,n, return_value = 1;
|
|
|
|
- stbrp_context *context = (stbrp_context *) spc->pack_info;
|
|
|
|
- stbrp_rect *rects;
|
|
|
|
|
|
+ int i,j,k;
|
|
|
|
|
|
- // flag all characters as NOT packed
|
|
|
|
- for (i=0; i < num_ranges; ++i)
|
|
|
|
- for (j=0; j < ranges[i].num_chars_in_range; ++j)
|
|
|
|
- ranges[i].chardata_for_range[j].x0 =
|
|
|
|
- ranges[i].chardata_for_range[j].y0 =
|
|
|
|
- ranges[i].chardata_for_range[j].x1 =
|
|
|
|
- ranges[i].chardata_for_range[j].y1 = 0;
|
|
|
|
-
|
|
|
|
- n = 0;
|
|
|
|
- for (i=0; i < num_ranges; ++i)
|
|
|
|
- n += ranges[i].num_chars_in_range;
|
|
|
|
-
|
|
|
|
- rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
|
|
|
|
- if (rects == NULL)
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
|
|
|
|
k=0;
|
|
k=0;
|
|
for (i=0; i < num_ranges; ++i) {
|
|
for (i=0; i < num_ranges; ++i) {
|
|
float fh = ranges[i].font_size;
|
|
float fh = ranges[i].font_size;
|
|
- float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh);
|
|
|
|
|
|
+ float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
|
|
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
|
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
|
int x0,y0,x1,y1;
|
|
int x0,y0,x1,y1;
|
|
- stbtt_GetCodepointBitmapBoxSubpixel(&info, ranges[i].first_unicode_char_in_range + j,
|
|
|
|
- scale * spc->h_oversample,
|
|
|
|
- scale * spc->v_oversample,
|
|
|
|
- 0,0,
|
|
|
|
- &x0,&y0,&x1,&y1);
|
|
|
|
|
|
+ int glyph = stbtt_FindGlyphIndex(info,ranges[i].first_unicode_char_in_range + j);
|
|
|
|
+ stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
|
|
|
|
+ scale * spc->h_oversample,
|
|
|
|
+ scale * spc->v_oversample,
|
|
|
|
+ 0,0,
|
|
|
|
+ &x0,&y0,&x1,&y1);
|
|
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
|
|
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
|
|
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
|
|
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
|
|
++k;
|
|
++k;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- stbrp_pack_rects(context, rects, k);
|
|
|
|
|
|
+ return k;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// rects array must be big enough to accommodate all characters in the given ranges
|
|
|
|
+STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
|
|
|
+{
|
|
|
|
+ float recip_h = 1.0f / spc->h_oversample;
|
|
|
|
+ float recip_v = 1.0f / spc->v_oversample;
|
|
|
|
+ float sub_x = stbtt__oversample_shift(spc->h_oversample);
|
|
|
|
+ float sub_y = stbtt__oversample_shift(spc->v_oversample);
|
|
|
|
+ int i,j,k, return_value = 1;
|
|
|
|
|
|
k = 0;
|
|
k = 0;
|
|
for (i=0; i < num_ranges; ++i) {
|
|
for (i=0; i < num_ranges; ++i) {
|
|
float fh = ranges[i].font_size;
|
|
float fh = ranges[i].font_size;
|
|
- float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh);
|
|
|
|
|
|
+ float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
|
|
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
|
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
|
stbrp_rect *r = &rects[k];
|
|
stbrp_rect *r = &rects[k];
|
|
if (r->was_packed) {
|
|
if (r->was_packed) {
|
|
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
|
|
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
|
|
int advance, lsb, x0,y0,x1,y1;
|
|
int advance, lsb, x0,y0,x1,y1;
|
|
- int glyph = stbtt_FindGlyphIndex(&info, ranges[i].first_unicode_char_in_range + j);
|
|
|
|
|
|
+ int glyph = stbtt_FindGlyphIndex(info, ranges[i].first_unicode_char_in_range + j);
|
|
stbrp_coord pad = (stbrp_coord) spc->padding;
|
|
stbrp_coord pad = (stbrp_coord) spc->padding;
|
|
|
|
|
|
// pad on left and top
|
|
// pad on left and top
|
|
@@ -2850,12 +2849,12 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd
|
|
r->y += pad;
|
|
r->y += pad;
|
|
r->w -= pad;
|
|
r->w -= pad;
|
|
r->h -= pad;
|
|
r->h -= pad;
|
|
- stbtt_GetGlyphHMetrics(&info, glyph, &advance, &lsb);
|
|
|
|
- stbtt_GetGlyphBitmapBox(&info, glyph,
|
|
|
|
|
|
+ stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
|
|
|
|
+ stbtt_GetGlyphBitmapBox(info, glyph,
|
|
scale * spc->h_oversample,
|
|
scale * spc->h_oversample,
|
|
scale * spc->v_oversample,
|
|
scale * spc->v_oversample,
|
|
&x0,&y0,&x1,&y1);
|
|
&x0,&y0,&x1,&y1);
|
|
- stbtt_MakeGlyphBitmapSubpixel(&info,
|
|
|
|
|
|
+ stbtt_MakeGlyphBitmapSubpixel(info,
|
|
spc->pixels + r->x + r->y*spc->stride_in_bytes,
|
|
spc->pixels + r->x + r->y*spc->stride_in_bytes,
|
|
r->w - spc->h_oversample+1,
|
|
r->w - spc->h_oversample+1,
|
|
r->h - spc->v_oversample+1,
|
|
r->h - spc->v_oversample+1,
|
|
@@ -2892,6 +2891,40 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ return return_value;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
|
|
|
|
+{
|
|
|
|
+ stbtt_fontinfo info;
|
|
|
|
+ int i,j,n, return_value = 1;
|
|
|
|
+ stbrp_context *context = (stbrp_context *) spc->pack_info;
|
|
|
|
+ stbrp_rect *rects;
|
|
|
|
+
|
|
|
|
+ // flag all characters as NOT packed
|
|
|
|
+ for (i=0; i < num_ranges; ++i)
|
|
|
|
+ for (j=0; j < ranges[i].num_chars_in_range; ++j)
|
|
|
|
+ ranges[i].chardata_for_range[j].x0 =
|
|
|
|
+ ranges[i].chardata_for_range[j].y0 =
|
|
|
|
+ ranges[i].chardata_for_range[j].x1 =
|
|
|
|
+ ranges[i].chardata_for_range[j].y1 = 0;
|
|
|
|
+
|
|
|
|
+ n = 0;
|
|
|
|
+ for (i=0; i < num_ranges; ++i)
|
|
|
|
+ n += ranges[i].num_chars_in_range;
|
|
|
|
+
|
|
|
|
+ rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
|
|
|
|
+ if (rects == NULL)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
|
|
|
|
+
|
|
|
|
+ n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
|
|
|
|
+
|
|
|
|
+ stbrp_pack_rects(context, rects, n);
|
|
|
|
+
|
|
|
|
+ return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
|
|
|
|
+
|
|
STBTT_free(rects, spc->user_allocator_context);
|
|
STBTT_free(rects, spc->user_allocator_context);
|
|
return return_value;
|
|
return return_value;
|
|
}
|
|
}
|