Last active
September 8, 2018 13:27
-
-
Save vassvik/82a356a7a2c0adf09d72f132fe3b854e to your computer and use it in GitHub Desktop.
Font atlas packing with stbtruetype.h, with optional colored visualization of packing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define STB_RECT_PACK_IMPLEMENTATION | |
#include "stb_rect_pack.h" // For better packing overall | |
#define STB_TRUETYPE_IMPLEMENTATION | |
#include "stb_truetype.h" | |
#define STB_IMAGE_WRITE_IMPLEMENTATION | |
#include "stb_image_write.h" // for saving png | |
/* | |
// this holds all the per-glyph data | |
typedef struct | |
{ | |
unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap | |
float xoff,yoff,xadvance; | |
float xoff2,yoff2; | |
} stbtt_packedchar; | |
*/ | |
/* | |
// this is used to specify which ranges of glyphs to pack | |
typedef struct | |
{ | |
float font_size; | |
int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint | |
int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints | |
int num_chars; | |
stbtt_packedchar *chardata_for_range; // output | |
unsigned char h_oversample, v_oversample; // don't set these, they're used internally | |
} stbtt_pack_range; | |
*/ | |
int main() { | |
FILE *fp = fopen("consola.ttf", "rb"); | |
int ttf_size_max = 1e6; // most likely large enough, 1MB | |
unsigned char *ttf_buffer = (unsigned char*)malloc(ttf_size_max); | |
fread(ttf_buffer, 1, ttf_size_max, fp); | |
fclose(fp); | |
// probably large enough | |
int width = 2048; | |
int height = 2048; | |
unsigned char *bitmap = (unsigned char*)malloc(height*width); | |
stbtt_pack_context pc; | |
stbtt_packedchar cdatas[100][95]; | |
stbtt_PackBegin(&pc, bitmap, width, height, 0, 1, NULL); | |
stbtt_PackSetOversampling(&pc, 3, 1); | |
int num_sizes = 17; | |
stbtt_pack_range ranges[99] = {{72, 32, NULL, 95, cdatas[0], 0, 0}, | |
{68, 32, NULL, 95, cdatas[1], 0, 0}, | |
{64, 32, NULL, 95, cdatas[2], 0, 0}, | |
{60, 32, NULL, 95, cdatas[3], 0, 0}, | |
{56, 32, NULL, 95, cdatas[4], 0, 0}, | |
{52, 32, NULL, 95, cdatas[5], 0, 0}, | |
{48, 32, NULL, 95, cdatas[6], 0, 0}, | |
{44, 32, NULL, 95, cdatas[7], 0, 0}, | |
{40, 32, NULL, 95, cdatas[8], 0, 0}, | |
{36, 32, NULL, 95, cdatas[9], 0, 0}, | |
{32, 32, NULL, 95, cdatas[10], 0, 0}, | |
{28, 32, NULL, 95, cdatas[11], 0, 0}, | |
{24, 32, NULL, 95, cdatas[12], 0, 0}, | |
{20, 32, NULL, 95, cdatas[13], 0, 0}, | |
{16, 32, NULL, 95, cdatas[14], 0, 0}, | |
{12, 32, NULL, 95, cdatas[15], 0, 0}, | |
{8, 32, NULL, 95, cdatas[16], 0, 0}}; | |
stbtt_PackFontRanges(&pc, ttf_buffer, 0, ranges, num_sizes); | |
stbtt_PackEnd(&pc); | |
// Calculate fill-rate (packing efficiency) | |
int filled = 0; | |
int max_y = 0; | |
for (int j = 0; j < num_sizes; j++) { | |
for (int i = 0; i < 95; i++) { | |
//printf("%d %d %d %d %d %d %f %f %f %f %f\n", j, i, cdatas[j][i].x0, cdatas[j][i].y0, cdatas[j][i].x1, cdatas[j][i].y1, | |
// cdatas[j][i].xoff, cdatas[j][i].yoff, cdatas[j][i].xoff2, cdatas[j][i].yoff2, | |
// cdatas[j][i].xadvance); | |
if (cdatas[j][i].y1 > max_y) { | |
max_y = cdatas[j][i].y1; | |
} | |
filled += (cdatas[j][i].x1 - cdatas[j][i].x0)*(cdatas[j][i].y1 - cdatas[j][i].y0); | |
} | |
} | |
printf("max_y = %d\n", max_y); | |
printf("fill rate = %f\n", filled/(double)(width*max_y)); | |
stbi_write_png("font_3x1.png", width, max_y, 1, bitmap, 0); | |
// create an image with each size/range having a unique color | |
printf("%d\n", 3*width*max_y); | |
unsigned char *bitmap_colored = (unsigned char*)malloc(3*width*max_y); | |
for (int j = 0; j < num_sizes; j++) { | |
double R = 0.5 + 0.5*cos(2.0*j+0*12.45); | |
double G = 0.5 + 0.5*cos(3.0*j+0*12.45); | |
double B = 0.5 + 0.5*cos(5.0*j+0*12.45); | |
for (int i = 0; i < 95; i++) { | |
for (int x = cdatas[j][i].x0; x < cdatas[j][i].x1; x++) { | |
for (int y = cdatas[j][i].y0; y < cdatas[j][i].y1; y++) { | |
float s = bitmap[y*width + x]; | |
bitmap_colored[3*(y*width + x)+0] = s*R; | |
bitmap_colored[3*(y*width + x)+1] = s*G; | |
bitmap_colored[3*(y*width + x)+2] = s*B; | |
} | |
} | |
} | |
} | |
stbi_write_png("font_3x1_color.png", width, max_y, 3, bitmap_colored, 0); | |
free(bitmap_colored); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment