Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 107 additions & 96 deletions src/font.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,54 +14,70 @@ typedef struct {
} Point;

typedef struct {
Point *items;
Point* items;
size_t count;
size_t capacity;
} Points;

int main()
{
FT_Library library = {0};

FT_Error error = FT_Init_FreeType(&library);
if (error) {
fprintf(stderr, "ERROR: Could not initialize FreeType2 library\n");
return 1;
int append_to_spline(Point* const p1, Point* const p2, Vector2* p, Spline* spline) {
Segment seg;
int advance;
if(p1->on) {
seg = (Segment){
.kind = SEGMENT_LINE,
.p1 = *p,
.p2 = p1->position,
};
*p = seg.p2;
advance = 1;
} else if(p2->on) {
seg = (Segment){
.kind = SEGMENT_QUAD,
.p1 = *p,
.p2 = p1->position,
.p3 = p2->position,
};
*p = seg.p3;
advance = 2;
} else {
seg = (Segment){
.kind = SEGMENT_QUAD,
.p1 = *p,
.p2 = p1->position,
.p3 = Vector2Lerp(p1->position, p2->position, 0.5),
};
*p = seg.p3;
advance = 1;
}
da_append(spline, seg);
return advance;
}

const char *const font_file_path = "./assets/Vollkorn-Regular.ttf";
void _Spline(Spline* ptr) { da_free(*ptr); }
void _Points(Points* ptr) { da_free(*ptr); }

FT_Face face;
error = FT_New_Face(library, font_file_path, 0, &face);
if (error == FT_Err_Unknown_File_Format) {
fprintf(stderr, "ERROR: `%s` has an unknown format\n", font_file_path);
return 1;
} else if (error) {
fprintf(stderr, "ERROR: Could not load file `%s`\n", font_file_path);
return 1;
}
#define printf(...) // NOTE supress output

// char c = '#';
// char c = 'x';
char c = 'Q';
// char c = '?';
// char c = 'O';
error = FT_Load_Char(face, c, FT_LOAD_DEFAULT);
void rasterize(FT_Face face, int ch, float scale) {
FT_Error error = FT_Load_Char(face, ch, FT_LOAD_DEFAULT);
// error = FT_Load_Glyph(face, 'Q', FT_LOAD_DEFAULT);
if (error) {
if(error) {
fprintf(stderr, "ERROR: could not load glyph\n");
return 1;
return /*1*/;
}

if(!face->glyph->outline.n_points)
return clear_grid(); // NOTE is empty, do nothing

long int min_x = LONG_MAX, max_x = LONG_MIN;
long int min_y = LONG_MAX, max_y = LONG_MIN;
for (int i = 0; i < face->glyph->outline.n_points; ++i) {
for(int i = 0; i < face->glyph->outline.n_points; ++i) {
FT_Vector p = face->glyph->outline.points[i];
unsigned char t = face->glyph->outline.tags[i];
if (min_x > p.x) min_x = p.x;
if (max_x < p.x) max_x = p.x;
if (min_y > p.y) min_y = p.y;
if (max_y < p.y) max_y = p.y;
if(min_x > p.x) min_x = p.x;
if(max_x < p.x) max_x = p.x;
if(min_y > p.y) min_y = p.y;
if(max_y < p.y) max_y = p.y;
printf("%ld %ld %d\n", p.x, p.y, t);
}

Expand All @@ -72,15 +88,13 @@ int main()
printf("n_contours = %d\n", face->glyph->outline.n_contours);
printf("------------------------------\n");

int factor = 100;
Points points = {0};
for (int pindex = 0; pindex <= face->glyph->outline.n_points; pindex++) {
[[gnu::cleanup(_Points)]] Points points = {0};
for(int pindex = 0; pindex <= face->glyph->outline.n_points; pindex++) {
FT_Vector p = face->glyph->outline.points[pindex];
unsigned char t = FT_CURVE_TAG(face->glyph->outline.tags[pindex]);
assert(t != FT_CURVE_TAG_CUBIC);
float scale = 0.5;
float x = (p.x - min_x)*scale + 100;
float y = (max_y - p.y)*scale + 100;
float x = (p.x - min_x) * scale + 100;
float y = (max_y - p.y) * scale + 100;
Point point = {
.position = {x, y},
.on = t == FT_CURVE_TAG_ON,
Expand All @@ -89,81 +103,79 @@ int main()
}

size_t contour_start = 0;
Spline spline = {0};
for (int i = 0; i < face->glyph->outline.n_contours; ++i) {
Point *contour = &points.items[contour_start];
[[gnu::cleanup(_Spline)]] Spline spline = {0};

for(int i = 0; i < face->glyph->outline.n_contours; ++i) {
size_t contour_size = face->glyph->outline.contours[i] - contour_start + 1;
assert(contour_size > 2);

Point* const contour_front = points.items + contour_start;
Point* const contour_back = contour_front + contour_size - 1;
Point* it = contour_front;
Vector2 p = {0};
size_t j = 0;
bool hack = false;
if (contour[0].on) {
p = contour[0].position;
j = 1;
hack = true;
} else if (contour[contour_size - 1].on) {
p = contour[contour_size - 1].position;
j = 0;
if(contour_back->on) {
p = contour_back->position;
} else if(contour_front->on) {
p = it++->position;
} else {
p = Vector2Lerp(contour[0].position, contour[contour_size - 1].position, 0.5);
j = 0;
}
printf("------------------------------\n");
printf("j = %zu\n", j);
printf("------------------------------\n");
while ((hack && j <= contour_size) || j < contour_size) {
if (contour[j%contour_size].on) {
Segment seg = {
.kind = SEGMENT_LINE,
.p1 = p,
.p2 = contour[j%contour_size].position,
};
da_append(&spline, seg);
p = contour[j%contour_size].position;
j += 1;
} else if (contour[(j+1)%contour_size].on) {
Segment seg = {
.kind = SEGMENT_QUAD,
.p1 = p,
.p2 = contour[j%contour_size].position,
.p3 = contour[(j+1)%contour_size].position,
};
da_append(&spline, seg);
p = contour[(j+1)%contour_size].position;
j += 2;
} else {
Vector2 v = Vector2Lerp(
contour[j%contour_size].position,
contour[(j+1)%contour_size].position,
0.5
);
Segment seg = {
.kind = SEGMENT_QUAD,
.p1 = p,
.p2 = contour[j%contour_size].position,
.p3 = v,
};
da_append(&spline, seg);
p = v;
j += 1;
}
p = Vector2Lerp(contour_front->position, contour_back->position, 0.5);
}
while(it < contour_back)
it += append_to_spline(it, it + 1, &p, &spline);
append_to_spline(contour_back, contour_front, &p, &spline);

contour_start = face->glyph->outline.contours[i] + 1;
}

printf("spline.count = %zu\n", spline.count);
render_spline_into_grid(&spline);
}

int main() {
FT_Library library = {0};

FT_Error error = FT_Init_FreeType(&library);
if(error) {
fprintf(stderr, "ERROR: Could not initialize FreeType2 library\n");
return 1;
}

const char* const font_file_path = "./assets/Vollkorn-Regular.ttf";

InitWindow(16*factor, 9*factor, "main");
FT_Face face;
error = FT_New_Face(library, font_file_path, 0, &face);
if(error == FT_Err_Unknown_File_Format) {
fprintf(stderr, "ERROR: `%s` has an unknown format\n", font_file_path);
return 1;
} else if(error) {
fprintf(stderr, "ERROR: Could not load file `%s`\n", font_file_path);
return 1;
}

int factor = 100;
SetTraceLogLevel(LOG_WARNING);
InitWindow(16 * factor, 9 * factor, "main");
SetTargetFPS(60);
while (!WindowShouldClose()) {
int ctr = 0;
int ch = L' ';
// int ch = '#';
// int ch = 'x';
// int ch = 'Q';
// int ch = '?';
// int ch = 'O';
// int ch = L'Ы';
// int ch = L'繁';//汉仪菱心体
// rasterize(face,ch, 0.5);
while(!WindowShouldClose()) {
ClearBackground(BLACK);
BeginDrawing();
if(!(++ctr % 5)) rasterize(face, ch++, 0.5);
display_grid();
EndDrawing();
}
CloseWindow();

FT_Done_FreeType(library);

// Types we are interested in
// - FT_Outline from ftimage.h
// - FT_Vector
Expand All @@ -175,7 +187,6 @@ int main()
// * outline's content easily.
// - FT_Glyph


printf("OK\n");
return 0;
}
16 changes: 10 additions & 6 deletions src/raster.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#define windows_factor 200
#define window_width (width_factor*windows_factor)
#define window_height (height_factor*windows_factor)
#define grid_factor 20
#define grid_factor 25
#define grid_width (width_factor*grid_factor)
#define grid_height (height_factor*grid_factor)
#define cell_width (window_width/grid_width)
Expand Down Expand Up @@ -135,14 +135,18 @@ void solve_row(const Spline *spline, size_t row, Solutions *solutions)
qsort(solutions->items, solutions->count, sizeof(*solutions->items), compare_solutions_by_tx);
}

void render_spline_into_grid(const Spline *spline)
{
static Solutions solutions = {0};
for (size_t row = 0; row < grid_height; ++row) {
for (size_t col = 0; col < grid_width; ++col) {
void clear_grid() {
for(size_t row = 0; row < grid_height; ++row) {
for(size_t col = 0; col < grid_width; ++col) {
grid[row][col] = false;
}
}
}

void render_spline_into_grid(const Spline *spline)
{
static Solutions solutions = {0};
clear_grid();
for (size_t row = 0; row < grid_height; ++row) {
int winding = 0;
solve_row(spline, row, &solutions);
Expand Down