parent
4162e6d302
commit
357884e2fb
@ -0,0 +1,3 @@ |
|||||||
|
*.ff |
||||||
|
*.png |
||||||
|
font-to-atlas |
@ -0,0 +1,2 @@ |
|||||||
|
font-to-atlas: main.c ff.c ff.h |
||||||
|
cc -lm -g main.c ff.c -o font-to-atlas
|
@ -0,0 +1,118 @@ |
|||||||
|
#include <arpa/inet.h> |
||||||
|
#include <unistd.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#include <stdio.h> |
||||||
|
|
||||||
|
#include "ff.h" |
||||||
|
|
||||||
|
|
||||||
|
#define MAX(a,b) a>b?a:b |
||||||
|
|
||||||
|
|
||||||
|
struct ff * ff_new(uint32_t width, uint32_t height) |
||||||
|
{ |
||||||
|
uint64_t size = (uint64_t)width*height*sizeof(struct ff); |
||||||
|
struct ff *image = malloc(sizeof(struct ff) + size); |
||||||
|
if (!image) |
||||||
|
return NULL; |
||||||
|
memcpy(image->magic, "farbfeld", 8); |
||||||
|
image->width = htonl(width); |
||||||
|
image->height = htonl(height); |
||||||
|
|
||||||
|
// create a transparent image
|
||||||
|
memset(image->pixels, 0, size); |
||||||
|
|
||||||
|
return image; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
uint64_t ff_bytes(const struct ff *image) |
||||||
|
{ |
||||||
|
if (!image) |
||||||
|
return 0; |
||||||
|
return sizeof(struct ff)+(uint64_t)ntohl(image->width)*ntohl(image->height)*sizeof(struct ff_px); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
struct ff * ff_resize(struct ff *image, uint32_t width, uint32_t height) |
||||||
|
{ |
||||||
|
struct ff *new = NULL; |
||||||
|
int64_t size = sizeof(struct ff)+(int64_t)width*height*sizeof(uint64_t); |
||||||
|
if (image) { |
||||||
|
int64_t old_size = ff_bytes(image); |
||||||
|
if (old_size == size) |
||||||
|
return image; |
||||||
|
|
||||||
|
new = realloc(image, size); |
||||||
|
if (!new) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
uint32_t old_width = ntohl(new->width); |
||||||
|
uint32_t old_height = ntohl(new->height); |
||||||
|
if (size-old_size > 0) { |
||||||
|
struct ff_px *b = new->pixels; |
||||||
|
memset(&b[old_width*old_height], 0, size-old_size); |
||||||
|
for (int64_t c = (int64_t)old_height-1; c >= 0; c--) { |
||||||
|
memmove(&b[width*c], &b[old_width*c], sizeof(struct ff_px)*old_width); |
||||||
|
memset(&b[c*old_width], 0, sizeof(struct ff_px)*(c*width-c*old_width)); |
||||||
|
} |
||||||
|
} else { |
||||||
|
} |
||||||
|
new->height = htonl(height); |
||||||
|
new->width = htonl(width); |
||||||
|
|
||||||
|
} else { |
||||||
|
new = ff_new(width, height); |
||||||
|
} |
||||||
|
|
||||||
|
return new; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int ff_verify (const struct ff *image) |
||||||
|
{ |
||||||
|
if (!image || strncmp("farbfeld", (char*)image->magic, 8)) |
||||||
|
return 1; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int ff_free(struct ff *image) |
||||||
|
{ |
||||||
|
if (!ff_verify(image)) |
||||||
|
free(image); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// overlays the bitmap containing only 1 8bpp channel to the image starting at (x,y)
|
||||||
|
// be stands for the data is already big endian
|
||||||
|
int ff_overlay_8r(struct ff **image, const uint8_t *bitmap, uint32_t x, uint32_t y, uint32_t w, uint32_t h) |
||||||
|
{ |
||||||
|
if (!image || !*image) |
||||||
|
return 1; |
||||||
|
|
||||||
|
uint32_t iw = ntohl((*image)->width), ih = ntohl((*image)->height); |
||||||
|
*image = ff_resize(*image, MAX(iw, x+w), MAX(ih, y+h)); |
||||||
|
if (!image) |
||||||
|
return -1; |
||||||
|
iw = ntohl((*image)->width); |
||||||
|
ih = ntohl((*image)->height); |
||||||
|
|
||||||
|
for (uint32_t r = 0; r < h; r++) { |
||||||
|
for (uint32_t c = 0; c < w; c++) { |
||||||
|
uint8_t col = bitmap[r*w+c]; |
||||||
|
struct ff_px p = { |
||||||
|
.r = 0xffff, |
||||||
|
.g = 0xffff, |
||||||
|
.b = 0xffff, |
||||||
|
.a = htons(257*col) |
||||||
|
}; |
||||||
|
(*image)->pixels[(r+y)*iw + (c+x)] = p; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
#ifndef _FARBFELD_EZ_H |
||||||
|
#define _FARBFELD_EZ_H |
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
|
||||||
|
struct __attribute__((packed)) ff_px { uint16_t r, g, b, a; }; |
||||||
|
|
||||||
|
struct __attribute__((packed)) ff { |
||||||
|
int8_t magic[8]; |
||||||
|
uint32_t width, height; |
||||||
|
struct ff_px pixels[]; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
struct ff * ff_new(uint32_t width, uint32_t height); |
||||||
|
int ff_verify (const struct ff *image); |
||||||
|
int ff_free(struct ff *image); |
||||||
|
uint64_t ff_bytes(const struct ff *image); |
||||||
|
struct ff * ff_resize(struct ff *image, uint32_t width, uint32_t height); |
||||||
|
int ff_overlay_8r(struct ff **image, const uint8_t *bitmap, uint32_t x, uint32_t y, uint32_t w, uint32_t h); |
||||||
|
|
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,107 @@ |
|||||||
|
#define _POSIX_C_SOURCE 200809l |
||||||
|
#define STB_TRUETYPE_IMPLEMENTATION |
||||||
|
#define STBTT_STATIC |
||||||
|
|
||||||
|
#include <sys/mman.h> |
||||||
|
|
||||||
|
#include <stdio.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <unistd.h> |
||||||
|
#include <errno.h> |
||||||
|
#include <err.h> |
||||||
|
|
||||||
|
#include "stb_truetype.h" |
||||||
|
#include "ff.h" |
||||||
|
|
||||||
|
|
||||||
|
const int font_size = 32; |
||||||
|
|
||||||
|
|
||||||
|
void map_file(const unsigned char **str, int *size, const char *path) |
||||||
|
{ |
||||||
|
if (!path) |
||||||
|
err(EXIT_FAILURE, "NULL filename"); |
||||||
|
FILE *fp = fopen(path, "r"); |
||||||
|
if (!fp) |
||||||
|
err(EXIT_FAILURE, "Cannot open file %s", path); |
||||||
|
*size = lseek(fileno(fp), 0, SEEK_END); |
||||||
|
if (*size == (off_t)-1) |
||||||
|
err(EXIT_FAILURE, "lseek failed"); |
||||||
|
*str = mmap(0, *size, PROT_READ, MAP_PRIVATE, fileno(fp), 0); |
||||||
|
if (*str == (void*)-1) |
||||||
|
err(EXIT_FAILURE, "mmap failed"); |
||||||
|
if (fclose(fp)) |
||||||
|
err(EXIT_FAILURE, "Error closing file"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) |
||||||
|
{ |
||||||
|
if (argc < 2) |
||||||
|
return EXIT_FAILURE; |
||||||
|
int len; |
||||||
|
const unsigned char *map; |
||||||
|
map_file(&map, &len, argv[1]); |
||||||
|
|
||||||
|
stbtt_fontinfo font; |
||||||
|
stbtt_InitFont(&font, map, stbtt_GetFontOffsetForIndex(map, 0)); |
||||||
|
|
||||||
|
// all this is to get the font bounding box in pixels
|
||||||
|
float font_scale = 1.0; |
||||||
|
font_scale = stbtt_ScaleForPixelHeight(&font, font_size); |
||||||
|
int ascent, descent, linegap; |
||||||
|
stbtt_GetFontVMetrics(&font, &ascent, &descent, &linegap); |
||||||
|
int x0,y0,x1,y1; |
||||||
|
int bound_w, bound_h; |
||||||
|
stbtt_GetFontBoundingBox(&font, &x0, &y0, &x1, &y1); |
||||||
|
|
||||||
|
printf("font_scale: %f\n", font_scale); |
||||||
|
printf("x0:%d y0:%d x1:%d y1:%d\n",x0,y0,x1,y1); |
||||||
|
|
||||||
|
int baseline = font_scale * -y0; |
||||||
|
bound_h = (baseline+font_scale*y1) - (baseline+font_scale*y0); |
||||||
|
bound_w = (font_scale*x1) - (font_scale*x0); |
||||||
|
baseline = bound_h - baseline; |
||||||
|
unsigned char *bitmap = malloc(bound_h*bound_w); |
||||||
|
if (!bitmap) |
||||||
|
err(EXIT_FAILURE, "Cannot allocate bitmap"); |
||||||
|
|
||||||
|
printf("bounding h:%d w:%d\n", bound_h, bound_w); |
||||||
|
printf("baseline: %d\n", baseline); |
||||||
|
|
||||||
|
struct ff *image = ff_new(0, 0); |
||||||
|
|
||||||
|
// get all ascii
|
||||||
|
int x = 0, y = 0, maxwidth = 64*bound_w; |
||||||
|
for (unsigned int i = 0; i <= 0x7F; i++) { |
||||||
|
int x0,y0,x1,y1,w,h,l,a, ox,oy; |
||||||
|
int g = stbtt_FindGlyphIndex(&font, i); |
||||||
|
|
||||||
|
stbtt_GetGlyphBitmapBoxSubpixel(&font, g, font_scale, font_scale, 0, 0, &x0, &y0, &x1, &y1); |
||||||
|
w = x1 - x0; |
||||||
|
h = y1 - y0; |
||||||
|
//printf("%d\n", y0);
|
||||||
|
stbtt_GetGlyphHMetrics(&font, g, &a, &l); |
||||||
|
stbtt_MakeGlyphBitmapSubpixel(&font, bitmap, w, h, w, font_scale, font_scale, 0, 0, g); |
||||||
|
//printf("'%c' -> l*scale:%.0f, y0:%d\n", i, font_scale*l, bound_h+y0);
|
||||||
|
ox = font_scale*l; |
||||||
|
oy = bound_h+y0; |
||||||
|
ff_overlay_8r(&image, bitmap, x+ox, y+oy, w, h); |
||||||
|
|
||||||
|
x += bound_w; |
||||||
|
if (x >= maxwidth) y += bound_h; |
||||||
|
x %= maxwidth; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
FILE *fp = fopen("out.ff", "w"); |
||||||
|
if (fp) { |
||||||
|
fwrite(image, 1, ff_bytes(image), fp); |
||||||
|
fclose(fp); |
||||||
|
} |
||||||
|
|
||||||
|
free(bitmap); |
||||||
|
ff_free(image); |
||||||
|
munmap((void *)map, len); |
||||||
|
return 0; |
||||||
|
} |
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue