Skip to content

Commit 16f75bd

Browse files
authored
Merge pull request #131 from sysprog21/improve-font-editor
Refine font-edit tool with O(n) curve fitting
2 parents e553031 + 9cc8a35 commit 16f75bd

File tree

4 files changed

+266
-165
lines changed

4 files changed

+266
-165
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ font-edit_cflags-y := \
175175
$(shell sdl2-config --cflags)
176176
font-edit_ldflags-y := \
177177
$(shell pkg-config --libs cairo) \
178-
$(shell sdl2-config --libs)
178+
$(shell sdl2-config --libs) \
179+
-lm
179180

180181
# Headless control tool
181182
target-$(CONFIG_TOOL_HEADLESS_CTL) += headless-ctl

tools/font-edit/font-edit.c

Lines changed: 143 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -39,27 +39,27 @@ static int offset;
3939

4040
static int offsets[1024];
4141

42-
/*
43-
* exit_window - bool. Control the life of the window.
42+
/* exit_window - bool. Control the life of the window.
4443
* if the value is false, the window remains open;
4544
* otherwise, the window closes.
4645
*/
4746
static bool exit_window = false;
4847

49-
static int init(int argc __attribute__((unused)),
50-
char **argv __attribute__((unused)))
48+
static void free_cmd(cmd_t *cmd);
49+
50+
static bool init(int argc maybe_unused, char **argv maybe_unused)
5151
{
5252
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
5353
printf("Failed to initialize SDL video. Reason: %s\n", SDL_GetError());
54-
return 0;
54+
return false;
5555
}
5656

5757
window = SDL_CreateWindow("Font Editor", SDL_WINDOWPOS_CENTERED,
5858
SDL_WINDOWPOS_CENTERED, width, height,
5959
SDL_WINDOW_SHOWN);
6060
if (!window) {
6161
printf("Failed to create SDL window. Reason: %s\n", SDL_GetError());
62-
return 0;
62+
return false;
6363
}
6464

6565
/* Create an SDL surface linked to the window */
@@ -76,30 +76,65 @@ static int init(int argc __attribute__((unused)),
7676
cairo_scale(cr, scale, scale);
7777

7878
cairo_set_font_size(cr, 2);
79-
return 1;
79+
return true;
80+
}
81+
82+
static void cleanup(void)
83+
{
84+
if (cr) {
85+
cairo_destroy(cr);
86+
cr = NULL;
87+
}
88+
if (surface) {
89+
cairo_surface_destroy(surface);
90+
surface = NULL;
91+
}
92+
if (window) {
93+
SDL_DestroyWindow(window);
94+
window = NULL;
95+
}
96+
SDL_Quit();
8097
}
8198

8299
static cmd_t *copy_cmd(cmd_t *cmd)
83100
{
84-
cmd_t *n = malloc(sizeof(cmd_t));
85101
if (!cmd)
86-
return 0;
87-
*n = *cmd;
88-
n->next = copy_cmd(cmd->next);
89-
return n;
102+
return NULL;
103+
104+
cmd_t *head = NULL;
105+
cmd_t **tail = &head;
106+
107+
while (cmd) {
108+
cmd_t *n = malloc(sizeof(cmd_t));
109+
if (!n) {
110+
/* Cleanup on failure */
111+
free_cmd(head);
112+
return NULL;
113+
}
114+
*n = *cmd;
115+
n->next = NULL;
116+
*tail = n;
117+
tail = &n->next;
118+
cmd = cmd->next;
119+
}
120+
121+
return head;
90122
}
91123

92124
static void free_cmd(cmd_t *cmd)
93125
{
94-
if (cmd) {
95-
free_cmd(cmd->next);
126+
while (cmd) {
127+
cmd_t *next = cmd->next;
96128
free(cmd);
129+
cmd = next;
97130
}
98131
}
99132

100133
static cmd_t *insert_cmd(cmd_t **prev)
101134
{
102135
cmd_t *n = malloc(sizeof(cmd_t));
136+
if (!n)
137+
return NULL;
103138

104139
n->op = op_noop;
105140
n->next = *prev;
@@ -124,13 +159,21 @@ static void delete_cmd(cmd_t **head, cmd_t *cmd)
124159
free(cmd);
125160
}
126161

127-
static void push(char_t *c)
162+
static bool push(char_t *c)
128163
{
129164
cmd_stack_t *s = malloc(sizeof(cmd_stack_t));
165+
if (!s)
166+
return false;
130167

131168
s->cmd = copy_cmd(c->cmd);
169+
if (!s->cmd && c->cmd) {
170+
free(s);
171+
return false;
172+
}
173+
132174
s->prev = c->stack;
133175
c->stack = s;
176+
return true;
134177
}
135178

136179
static void pop(char_t *c)
@@ -148,7 +191,8 @@ static void pop(char_t *c)
148191

149192
static void delete_first_cmd(char_t *c, cmd_t *first)
150193
{
151-
push(c);
194+
if (!push(c))
195+
fprintf(stderr, "Warning: cannot save undo state\n");
152196
delete_cmd(&c->cmd, first);
153197
c->first = c->last = 0;
154198
}
@@ -171,6 +215,9 @@ static int commas(char *line)
171215
static char_t *read_char(FILE *file)
172216
{
173217
char_t *c = malloc(sizeof(char_t));
218+
if (!c)
219+
return NULL;
220+
174221
char line[1024];
175222
cmd_t *cmd;
176223

@@ -195,16 +242,22 @@ static char_t *read_char(FILE *file)
195242
switch (line[5]) {
196243
case 'm':
197244
cmd = append_cmd(c);
245+
if (!cmd)
246+
goto error;
198247
cmd->op = op_move;
199248
sscanf(line + 8, "%lf, %lf", &cmd->pt[0].x, &cmd->pt[0].y);
200249
break;
201250
case 'l':
202251
cmd = append_cmd(c);
252+
if (!cmd)
253+
goto error;
203254
cmd->op = op_line;
204255
sscanf(line + 8, "%lf, %lf", &cmd->pt[0].x, &cmd->pt[0].y);
205256
break;
206257
case 'c':
207258
cmd = append_cmd(c);
259+
if (!cmd)
260+
goto error;
208261
cmd->op = op_curve;
209262
sscanf(line + 8, "%lf, %lf, %lf, %lf, %lf, %lf", &cmd->pt[0].x,
210263
&cmd->pt[0].y, &cmd->pt[1].x, &cmd->pt[1].y, &cmd->pt[2].x,
@@ -214,7 +267,18 @@ static char_t *read_char(FILE *file)
214267
return c;
215268
}
216269
}
217-
return 0;
270+
return NULL;
271+
272+
error:
273+
free_cmd(c->cmd);
274+
while (c->stack) {
275+
cmd_stack_t *s = c->stack;
276+
c->stack = s->prev;
277+
free_cmd(s->cmd);
278+
free(s);
279+
}
280+
free(c);
281+
return NULL;
218282
}
219283

220284
#define DOT_SIZE 1
@@ -408,9 +472,13 @@ static bool is_before(cmd_t *before, cmd_t *after)
408472
{
409473
if (!before)
410474
return false;
411-
if (before->next == after)
412-
return true;
413-
return is_before(before->next, after);
475+
476+
while (before) {
477+
if (before->next == after)
478+
return true;
479+
before = before->next;
480+
}
481+
return false;
414482
}
415483

416484
static void order(cmd_t **first_p, cmd_t **last_p)
@@ -425,18 +493,28 @@ static void order(cmd_t **first_p, cmd_t **last_p)
425493
static void replace_with_spline(char_t *c, cmd_t *first, cmd_t *last)
426494
{
427495
pts_t *pts = new_pts();
496+
if (!pts) {
497+
fprintf(stderr, "Error: out of memory\n");
498+
return;
499+
}
500+
428501
spline_t s;
429502
cmd_t *cmd, *next, *save;
430503

431504
order(&first, &last);
432505
for (cmd = first; cmd != last->next; cmd = cmd->next) {
433506
int i = cmd->op == op_curve ? 2 : 0;
434-
add_pt(pts, &cmd->pt[i]);
507+
if (!add_pt(pts, &cmd->pt[i])) {
508+
dispose_pts(pts);
509+
fprintf(stderr, "Error: out of memory\n");
510+
return;
511+
}
435512
}
436513

437514
s = fit(pts->pt, pts->n);
438515

439-
push(c);
516+
if (!push(c))
517+
fprintf(stderr, "Warning: cannot save undo state\n");
440518

441519
save = last->next;
442520

@@ -446,6 +524,12 @@ static void replace_with_spline(char_t *c, cmd_t *first, cmd_t *last)
446524
}
447525

448526
cmd = insert_cmd(&first->next);
527+
if (!cmd) {
528+
pop(c);
529+
dispose_pts(pts);
530+
fprintf(stderr, "Error: out of memory\n");
531+
return;
532+
}
449533

450534
cmd->op = op_curve;
451535
cmd->pt[0] = s.b;
@@ -460,13 +544,23 @@ static void split(char_t *c, cmd_t *first, cmd_t *last)
460544
{
461545
cmd_t *cmd;
462546

463-
push(c);
547+
if (!push(c))
548+
fprintf(stderr, "Warning: cannot save undo state\n");
464549
cmd = insert_cmd(&first->next);
550+
if (!cmd) {
551+
pop(c);
552+
fprintf(stderr, "Error: out of memory\n");
553+
return;
554+
}
465555
cmd->op = op_line;
466556
cmd->pt[0] = lerp(&first->pt[0], &last->pt[0]);
467557
if (last->op == op_move) {
468558
cmd_t *extra = insert_cmd(&last->next);
469-
559+
if (!extra) {
560+
pop(c);
561+
fprintf(stderr, "Error: out of memory\n");
562+
return;
563+
}
470564
extra->op = op_line;
471565
extra->pt[0] = last->pt[0];
472566
last->pt[0] = cmd->pt[0];
@@ -482,7 +576,8 @@ static void tweak_spline(char_t *c,
482576
{
483577
int i = !!is_2nd_point;
484578

485-
push(c);
579+
if (!push(c))
580+
fprintf(stderr, "Warning: cannot save undo state\n");
486581
first->pt[i].x += dx;
487582
first->pt[i].y += dy;
488583
}
@@ -658,6 +753,21 @@ static void generate_font_metrics(void)
658753
printf("\n");
659754
}
660755

756+
static void free_char(char_t *c)
757+
{
758+
if (!c)
759+
return;
760+
761+
free_cmd(c->cmd);
762+
while (c->stack) {
763+
cmd_stack_t *s = c->stack;
764+
c->stack = s->prev;
765+
free_cmd(s->cmd);
766+
free(s);
767+
}
768+
free(c);
769+
}
770+
661771
int main(int argc, char **argv)
662772
{
663773
char_t *c;
@@ -673,16 +783,22 @@ int main(int argc, char **argv)
673783
return 2;
674784
}
675785

676-
if (!init(argc, argv))
677-
exit(1);
786+
if (!init(argc, argv)) {
787+
fclose(file);
788+
return 1;
789+
}
790+
678791
while ((c = read_char(file)) && !exit_window) {
679792
play(c);
680793
print_char(c);
794+
free_char(c);
681795
}
682796

683797
fclose(file);
684798

685799
generate_font_metrics();
686800

801+
cleanup();
802+
687803
return 0;
688804
}

tools/font-edit/font-edit.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@
2424
#define _TWIN_FEDIT_H_
2525

2626
#include <math.h>
27+
#include <stdbool.h>
2728
#include <stdio.h>
2829
#include <stdlib.h>
2930
#include <string.h>
3031
#include <unistd.h>
3132

33+
#define maybe_unused __attribute__((unused))
34+
3235
/* Geometric types */
3336

3437
/*
@@ -104,8 +107,10 @@ void dispose_pts(pts_t *pts);
104107
* add_pt() - Add a point to pts_t
105108
* @pts: the object that receives the added points
106109
* @pt: the point to be added
110+
*
111+
* Return: true on success, false on memory allocation failure
107112
*/
108-
void add_pt(pts_t *pts, pt_t *pt);
113+
bool add_pt(pts_t *pts, pt_t *pt);
109114

110115
/*
111116
* distance_to_point() - Calculate distance between two points

0 commit comments

Comments
 (0)