Skip to content

Commit f139103

Browse files
authored
Adjust ttf API to expose names (#172)
* Adjust ttf API to expose names
1 parent b94f21e commit f139103

3 files changed

Lines changed: 68 additions & 55 deletions

File tree

pdfgen.c

Lines changed: 60 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,18 +1158,21 @@ int pdf_set_font(struct pdf_doc *pdf, const char *font)
11581158
return 0;
11591159
}
11601160

1161-
int pdf_set_font_ttf(struct pdf_doc *pdf, const char *path)
1161+
const char *pdf_set_font_ttf(struct pdf_doc *pdf, const char *path)
11621162
{
11631163
FILE *fp = fopen(path, "rb");
1164-
if (!fp)
1165-
return pdf_set_err(pdf, -errno, "Unable to open font file '%s': %s",
1166-
path, strerror(errno));
1167-
int err = pdf_set_font_ttf_file(pdf, fp, path);
1164+
if (!fp) {
1165+
pdf_set_err(pdf, -errno, "Unable to open font file '%s': %s", path,
1166+
strerror(errno));
1167+
return NULL;
1168+
}
1169+
const char *res = pdf_set_font_ttf_file(pdf, fp, path);
11681170
fclose(fp);
1169-
return err;
1171+
return res;
11701172
}
11711173

1172-
int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
1174+
const char *pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp,
1175+
const char *path)
11731176
{
11741177
uint8_t *font_data;
11751178
size_t font_data_len;
@@ -1191,34 +1194,39 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
11911194
struct stat st;
11921195

11931196
if (fstat(fileno(fp), &st) < 0) {
1194-
return pdf_set_err(pdf, -errno, "Unable to stat font file '%s': %s",
1195-
path, strerror(errno));
1197+
pdf_set_err(pdf, -errno, "Unable to stat font file '%s': %s", path,
1198+
strerror(errno));
1199+
return NULL;
11961200
}
11971201
font_data_len = (size_t)st.st_size;
11981202
font_data = (uint8_t *)malloc(font_data_len);
11991203
if (!font_data) {
1200-
return pdf_set_err(pdf, -ENOMEM,
1201-
"Unable to allocate %zu bytes for font '%s'",
1202-
font_data_len, path);
1204+
pdf_set_err(pdf, -ENOMEM,
1205+
"Unable to allocate %zu bytes for font '%s'",
1206+
font_data_len, path);
1207+
return NULL;
12031208
}
12041209
if (fread(font_data, 1, font_data_len, fp) != font_data_len) {
12051210
free(font_data);
1206-
return pdf_set_err(pdf, -EIO, "Unable to read font file '%s'", path);
1211+
pdf_set_err(pdf, -EIO, "Unable to read font file '%s'", path);
1212+
return NULL;
12071213
}
12081214

12091215
if (font_data_len < 12) {
12101216
free(font_data);
1211-
return pdf_set_err(
1212-
pdf, -EINVAL, "Font file '%s' is too small to be a TrueType font",
1213-
path);
1217+
pdf_set_err(pdf, -EINVAL,
1218+
"Font file '%s' is too small to be a TrueType font",
1219+
path);
1220+
return NULL;
12141221
}
12151222
sfVersion = ttf_be32(font_data);
12161223
// TrueType fonts have sfVersion 0x00010000 or 'true' (0x74727565)
12171224
if (sfVersion != 0x00010000u && sfVersion != 0x74727565u) {
12181225
free(font_data);
1219-
return pdf_set_err(
1220-
pdf, -EINVAL, "File '%s' is not a TrueType font (version 0x%08x)",
1221-
path, sfVersion);
1226+
pdf_set_err(pdf, -EINVAL,
1227+
"File '%s' is not a TrueType font (version 0x%08x)", path,
1228+
sfVersion);
1229+
return NULL;
12221230
}
12231231

12241232
head = ttf_find_table(font_data, font_data_len, "head", &head_len);
@@ -1231,9 +1239,9 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
12311239

12321240
if (!head || head_len < 54 || !hhea || hhea_len < 36 || !hmtx || !cmap) {
12331241
free(font_data);
1234-
return pdf_set_err(pdf, -EINVAL,
1235-
"Font '%s' is missing required TrueType tables",
1236-
path);
1242+
pdf_set_err(pdf, -EINVAL,
1243+
"Font '%s' is missing required TrueType tables", path);
1244+
return NULL;
12371245
}
12381246

12391247
// Parse head table
@@ -1245,8 +1253,8 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
12451253
macStyle = ttf_be16(head + 44);
12461254
if (units_per_em == 0) {
12471255
free(font_data);
1248-
return pdf_set_err(pdf, -EINVAL, "Font '%s' has zero units_per_em",
1249-
path);
1256+
pdf_set_err(pdf, -EINVAL, "Font '%s' has zero units_per_em", path);
1257+
return NULL;
12501258
}
12511259

12521260
// Parse hhea table
@@ -1318,7 +1326,7 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
13181326
if (obj->font.is_ttf && strcmp(obj->font.name, font_name) == 0) {
13191327
free(font_data);
13201328
pdf->current_font = obj;
1321-
return 0;
1329+
return obj->font.name;
13221330
}
13231331
last_font_index = obj->font.index;
13241332
}
@@ -1331,40 +1339,42 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
13311339
if (!cmap_subtable || cmap_subtable_len == 0 ||
13321340
cmap_subtable_len > font_data_len) {
13331341
free(font_data);
1334-
return pdf_set_err(pdf, -EINVAL,
1335-
"Font '%s' has no usable cmap subtable", path);
1342+
pdf_set_err(pdf, -EINVAL, "Font '%s' has no usable cmap subtable",
1343+
path);
1344+
return NULL;
13361345
}
13371346
uint8_t *cmap_copy = (uint8_t *)malloc(cmap_subtable_len);
13381347
if (!cmap_copy) {
13391348
free(font_data);
1340-
return pdf_set_err(pdf, -ENOMEM,
1341-
"Unable to allocate cmap subtable for font '%s'",
1342-
path);
1349+
pdf_set_err(pdf, -ENOMEM,
1350+
"Unable to allocate cmap subtable for font '%s'", path);
1351+
return NULL;
13431352
}
13441353
// ensure subtable fits in cmap bounds safely before blind copy
13451354
if (cmap_subtable_len > (cmap + cmap_len) - cmap_subtable) {
13461355
free(cmap_copy);
13471356
free(font_data);
1348-
return pdf_set_err(pdf, -EINVAL,
1349-
"Font '%s' cmap subtable length invalid", path);
1357+
pdf_set_err(pdf, -EINVAL, "Font '%s' cmap subtable length invalid",
1358+
path);
1359+
return NULL;
13501360
}
13511361
memcpy(cmap_copy, cmap_subtable, cmap_subtable_len);
13521362

13531363
if (hmtx_len == 0 || hmtx_len > font_data_len) {
13541364
free(cmap_copy);
13551365
free(font_data);
1356-
return pdf_set_err(pdf, -EINVAL, "Font '%s' has invalid hmtx_len",
1357-
path);
1366+
pdf_set_err(pdf, -EINVAL, "Font '%s' has invalid hmtx_len", path);
1367+
return NULL;
13581368
}
13591369

13601370
// Make a copy of the hmtx table for runtime advance-width lookups
13611371
uint8_t *hmtx_copy = (uint8_t *)malloc(hmtx_len);
13621372
if (!hmtx_copy) {
13631373
free(cmap_copy);
13641374
free(font_data);
1365-
return pdf_set_err(pdf, -ENOMEM,
1366-
"Unable to allocate hmtx table for font '%s'",
1367-
path);
1375+
pdf_set_err(pdf, -ENOMEM,
1376+
"Unable to allocate hmtx table for font '%s'", path);
1377+
return NULL;
13681378
}
13691379
memcpy(hmtx_copy, hmtx, hmtx_len);
13701380

@@ -1376,18 +1386,19 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
13761386
free(hmtx_copy);
13771387
free(cmap_copy);
13781388
free(font_data);
1379-
return pdf_set_err(pdf, -EINVAL,
1380-
"Font '%s' has invalid numberOfHMetrics", path);
1389+
pdf_set_err(pdf, -EINVAL, "Font '%s' has invalid numberOfHMetrics",
1390+
path);
1391+
return NULL;
13811392
}
13821393
uint16_t *glyph_widths =
13831394
(uint16_t *)calloc(numberOfHMetrics, sizeof(uint16_t));
13841395
if (!glyph_widths) {
13851396
free(hmtx_copy);
13861397
free(cmap_copy);
13871398
free(font_data);
1388-
return pdf_set_err(pdf, -ENOMEM,
1389-
"Unable to allocate glyph widths for font '%s'",
1390-
path);
1399+
pdf_set_err(pdf, -ENOMEM,
1400+
"Unable to allocate glyph widths for font '%s'", path);
1401+
return NULL;
13911402
}
13921403
for (uint16_t g = 0; g < numberOfHMetrics; g++) {
13931404
uint16_t advance =
@@ -1406,7 +1417,7 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
14061417
free(hmtx_copy);
14071418
free(cmap_copy);
14081419
free(font_data);
1409-
return pdf->errval;
1420+
return NULL;
14101421
}
14111422
dstr_printf(&stream_obj->stream.stream,
14121423
"<<\r\n"
@@ -1420,8 +1431,8 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
14201431
free(hmtx_copy);
14211432
free(cmap_copy);
14221433
free(font_data);
1423-
return pdf_set_err(pdf, -ENOMEM,
1424-
"Unable to allocate font stream data");
1434+
pdf_set_err(pdf, -ENOMEM, "Unable to allocate font stream data");
1435+
return NULL;
14251436
}
14261437
dstr_append(&stream_obj->stream.stream, "\r\nendstream\r\n");
14271438
free(font_data);
@@ -1432,7 +1443,7 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
14321443
free(glyph_widths);
14331444
free(hmtx_copy);
14341445
free(cmap_copy);
1435-
return pdf->errval;
1446+
return NULL;
14361447
}
14371448
strncpy(descriptor_obj->font_descriptor.font_name, font_name,
14381449
sizeof(descriptor_obj->font_descriptor.font_name) - 1);
@@ -1461,7 +1472,7 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
14611472
free(glyph_widths);
14621473
free(hmtx_copy);
14631474
free(cmap_copy);
1464-
return pdf->errval;
1475+
return NULL;
14651476
}
14661477
strncpy(cid_obj->cid_font.font_name, font_name,
14671478
sizeof(cid_obj->cid_font.font_name) - 1);
@@ -1477,7 +1488,7 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
14771488
if (!font_obj) {
14781489
free(hmtx_copy);
14791490
free(cmap_copy);
1480-
return pdf->errval;
1491+
return NULL;
14811492
}
14821493
strncpy(font_obj->font.name, font_name, sizeof(font_obj->font.name) - 1);
14831494
font_obj->font.name[sizeof(font_obj->font.name) - 1] = '\0';
@@ -1493,7 +1504,7 @@ int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path)
14931504
font_obj->font.cid_font_index = cid_obj->index;
14941505

14951506
pdf->current_font = font_obj;
1496-
return 0;
1507+
return font_obj->font.name;
14971508
}
14981509

14991510
struct pdf_object *pdf_append_page(struct pdf_doc *pdf)

pdfgen.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,10 @@ int pdf_set_font(struct pdf_doc *pdf, const char *font);
338338
* and will remain until pdf_set_font or pdf_set_font_ttf is called again.
339339
* @param pdf PDF document to update font on
340340
* @param path Filesystem path to a TrueType (.ttf) font file
341-
* @return < 0 on failure, 0 on success
341+
* @return NULL on failure, name of the font to use on success (this is used
342+
* for pdf_get_font_text_width)
342343
*/
343-
int pdf_set_font_ttf(struct pdf_doc *pdf, const char *path);
344+
const char *pdf_set_font_ttf(struct pdf_doc *pdf, const char *path);
344345

345346
/**
346347
* Sets the font to use for text objects by loading a TrueType font file from
@@ -349,9 +350,10 @@ int pdf_set_font_ttf(struct pdf_doc *pdf, const char *path);
349350
* @param pdf PDF document to update font on
350351
* @param fp TTF font file pointer (must be readable and seekable)
351352
* @param path Name of font for error messages and for internal PDF reference
352-
* @return < 0 on failure, 0 on success
353+
* @return NULL on failure, name of the font to use on success
353354
*/
354-
int pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp, const char *path);
355+
const char *pdf_set_font_ttf_file(struct pdf_doc *pdf, FILE *fp,
356+
const char *path);
355357

356358
/**
357359
* Calculate the width of a given string in the current font

tests/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ int main(int argc, char *argv[])
288288
const char *ttf_path = "data/Ithaca.ttf";
289289
pdf_append_page(pdf);
290290
pdf_add_bookmark(pdf, NULL, -1, "TrueType Font (Unicode)");
291-
if (pdf_set_font_ttf(pdf, ttf_path) < 0) {
291+
if (pdf_set_font_ttf(pdf, ttf_path) == NULL) {
292292
fprintf(stderr, "Failed to load TTF font: %s\n",
293293
pdf_get_err(pdf, &err));
294294
pdf_destroy(pdf);
@@ -346,7 +346,7 @@ int main(int argc, char *argv[])
346346
12, 50, 600, 0, PDF_BLACK, 300, PDF_ALIGN_LEFT, NULL);
347347

348348
// Reload the same font (should reuse the existing object)
349-
if (pdf_set_font_ttf(pdf, ttf_path) < 0) {
349+
if (pdf_set_font_ttf(pdf, ttf_path) == NULL) {
350350
fprintf(stderr, "Failed to reload TTF font\n");
351351
pdf_destroy(pdf);
352352
return -1;

0 commit comments

Comments
 (0)