aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2023-01-08 21:40:02 +0100
committerMattias Andrée <maandree@kth.se>2023-01-08 21:40:02 +0100
commit17a93f72f3343e6839f625972ba743ec61441c49 (patch)
tree7fc53e253e9e2aefad0f9a8d10edff0524198c75
parentFix error handling (diff)
downloadlibfonts-17a93f72f3343e6839f625972ba743ec61441c49.tar.gz
libfonts-17a93f72f3343e6839f625972ba743ec61441c49.tar.bz2
libfonts-17a93f72f3343e6839f625972ba743ec61441c49.tar.xz
Partially implement libfonts_get_default_font, libfonts_get_{default,output}_rendering_settings
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--Makefile8
-rw-r--r--common.h35
-rw-r--r--libfonts_confsplit__.c44
-rw-r--r--libfonts_get_default_font.c90
-rw-r--r--libfonts_get_default_rendering_settings.c82
-rw-r--r--libfonts_get_output_rendering_settings.c108
-rw-r--r--libfonts_getenv__.c14
-rw-r--r--libfonts_gethome__.c14
-rw-r--r--libfonts_getline__.c65
-rw-r--r--libfonts_parse_aa__.c51
-rw-r--r--libfonts_parse_double__.c23
-rw-r--r--libfonts_parse_order__.c105
-rw-r--r--libfonts_parse_uint32__.c36
13 files changed, 648 insertions, 27 deletions
diff --git a/Makefile b/Makefile
index c915208..71676a7 100644
--- a/Makefile
+++ b/Makefile
@@ -31,15 +31,21 @@ PUBLIC_OBJ =\
OBJ =\
$(PUBLIC_OBJ)\
+ libfonts_confsplit__.o\
libfonts_getenv__.o\
libfonts_gethome__.o\
+ libfonts_getline__.o\
+ libfonts_parse_aa__.o\
+ libfonts_parse_double__.o\
+ libfonts_parse_order__.o\
+ libfonts_parse_uint32__.o
HDR =\
common.h\
libfonts.h
LOBJ = $(OBJ:.o=.lo)
-TESTS = $(PUBLIC_OBJ:.o=.test)
+TESTS = $(OBJ:.o=.test)
all: libfonts.a libfonts.$(LIBEXT) $(TESTS)
diff --git a/common.h b/common.h
index 99298f1..082f806 100644
--- a/common.h
+++ b/common.h
@@ -2,6 +2,7 @@
#include "libfonts.h"
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <pwd.h>
@@ -11,22 +12,23 @@
#include <string.h>
#include <strings.h>
+
#define DOUBLE_TOLERANCE 0.000001
#define LIST_RENDERING_SETTINGS(X, _)\
- X("dpi-x", dpi_x, 96) _\
- X("dpi-y", dpi_y, 96) _\
- X("ref-width", reference_width, 0) _\
- X("ref-height", reference_height, 0) _\
- X("subpixel-order", subpixel_order, LIBFONTS_SUBPIXEL_ORDER_UNKNOWN) _\
- X("greyscale-min", min_dpsqi_for_greyscale, 0) _\
- X("subpixel-min", min_dpsqi_for_subpixel, 0) _\
- X("h-grey-text-aa", horizontal_grey_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE) _\
- X("v-grey-text-aa", vertical_grey_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE) _\
- X("d-grey-text-aa", diagonal_grey_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE) _\
- X("h-coloured-text-aa", horizontal_colour_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE) _\
- X("v-coloured-text-aa", vertical_colour_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE) _\
- X("d-coloured-text-aa", diagonal_colour_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE)
+ X(0, "dpi-x", dpi_x, 96, libfonts_parse_double__) _\
+ X(1, "dpi-y", dpi_y, 96, libfonts_parse_double__) _\
+ X(2, "ref-width", reference_width, 0, libfonts_parse_uint32__) _\
+ X(3, "ref-height", reference_height, 0, libfonts_parse_uint32__) _\
+ X(4, "subpixel-order", subpixel_order, LIBFONTS_SUBPIXEL_ORDER_UNKNOWN, libfonts_parse_order__) _\
+ X(5, "greyscale-min", min_dpsqi_for_greyscale, 0, libfonts_parse_double__) _\
+ X(6, "subpixel-min", min_dpsqi_for_subpixel, 0, libfonts_parse_double__) _\
+ X(7, "h-grey-text-aa", horizontal_grey_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE, libfonts_parse_aa__) _\
+ X(8, "v-grey-text-aa", vertical_grey_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE, libfonts_parse_aa__) _\
+ X(9, "d-grey-text-aa", diagonal_grey_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE, libfonts_parse_aa__) _\
+ X(10, "h-coloured-text-aa", horizontal_colour_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE, libfonts_parse_aa__) _\
+ X(11, "v-coloured-text-aa", vertical_colour_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE, libfonts_parse_aa__) _\
+ X(12, "d-coloured-text-aa", diagonal_colour_text_antialiasing, LIBFONTS_ANTIALIASING_GREYSCALE, libfonts_parse_aa__)
static inline void
@@ -50,6 +52,13 @@ eq(double a, double b)
const char *libfonts_getenv__(const char *name, struct libfonts_context *ctx);
char *libfonts_gethome__(struct libfonts_context *ctx);
+ssize_t libfonts_getline__(int fd, char **linep, char **bufp, size_t *sizep, size_t *offp, size_t *availp);
+char *libfonts_confsplit__(char *line);
+
+int libfonts_parse_double__(double *outp, const char *value);
+int libfonts_parse_uint32__(uint32_t *outp, const char *value);
+int libfonts_parse_order__(enum libfonts_subpixel_order *outp, const char *value);
+int libfonts_parse_aa__(enum libfonts_antialiasing *outp, const char *value);
#ifdef TEST
diff --git a/libfonts_confsplit__.c b/libfonts_confsplit__.c
new file mode 100644
index 0000000..959a4b4
--- /dev/null
+++ b/libfonts_confsplit__.c
@@ -0,0 +1,44 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+char *
+libfonts_confsplit__(char *line)
+{
+ size_t p, q;
+
+ p = 0;
+ while (line[p] && line[p] != '=')
+ p += 1;
+ if (!line[p])
+ return NULL;
+
+ q = p;
+ while (q && isblank(line[q - 1]))
+ q -= 1;
+ if (!q)
+ return NULL;
+ line[q] = '\0';
+
+ p++;
+ while (isblank(line[p]))
+ p++;
+ if (!line[p])
+ return NULL;
+
+ return &line[p];
+}
+
+
+#else
+
+
+int
+main(void)
+{
+ return 0; /* TODO add test */
+}
+
+
+#endif
diff --git a/libfonts_get_default_font.c b/libfonts_get_default_font.c
index 98e60d7..f8809bc 100644
--- a/libfonts_get_default_font.c
+++ b/libfonts_get_default_font.c
@@ -15,6 +15,13 @@ getn(char **outp, const char *file_part1, size_t file_part1_len, const char *fil
{
size_t file_part2_len = strlen(file_part2);
char *path;
+ int fd;
+ ssize_t len;
+ char *line, *buf = NULL;
+ size_t size = 0, off = 0, avail = 0;
+ char *value;
+
+ *outp = NULL;
if (file_part1_len > SIZE_MAX - file_part2_len - 1)
goto enomem;
@@ -29,14 +36,85 @@ getn(char **outp, const char *file_part1, size_t file_part1_len, const char *fil
memcpy(path, file_part1, file_part1_len);
memcpy(&path[file_part1_len], file_part2, file_part2_len + 1);
- /* TODO
- * sans-serif = $FONTNAME
- * serif = $FONTNAME
- * monospace = $FONTNAME
- */
+open_again:
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ switch (errno) {
+ case EINTR:
+ goto open_again;
+ case EMFILE:
+ case ENFILE:
+ case ENOMEM:
+ case ENOSPC:
+ free(path);
+ return -1;
+ case EFBIG:
+ case EOVERFLOW:
+ case EISDIR:
+ case ELOOP:
+ case ENODEV:
+ case ENOTDIR:
+ case ENXIO:
+ /* TODO print warning using `ctx` */
+ goto out;
+ default:
+ goto out;
+ }
+ }
+ for (;;) {
+ len = libfonts_getline__(fd, &line, &buf, &size, &off, &avail);
+ if (len < 0) {
+ if (errno == EINTR)
+ continue;
+ free(*outp);
+ *outp = NULL;
+ fail:
+ free(buf);
+ free(path);
+ close(fd);
+ return -1;
+ }
+ if (!len)
+ break;
+ line[len -= 1] = '\0';
+
+ while (isblank(*line)) {
+ line++;
+ len--;
+ }
+ if (!*line || *line == '#')
+ continue;
+ while (len && isblank(line[len - 1]))
+ len -= 1;
+ line[len] = '\0';
+
+ value = libfonts_confsplit__(line);
+ if (!value) {
+ /* TODO warning */
+ continue;
+ }
+
+ if (!strcmp(line, name)) {
+ if (*outp) {
+ /* TODO warning */
+ free(*outp);
+ *outp = NULL;
+ }
+ *outp = strdup(value);
+ if (!*outp)
+ goto fail;
+ } else if (strcmp(line, "sans-serif") && strcmp(line, "serif") && strcmp(line, "monospace")) {
+ /* TODO warning */
+ }
+ }
+
+ free(buf);
+ close(fd);
+
+out:
free(path);
- return 0;
+ return *outp != NULL;
}
static int
diff --git a/libfonts_get_default_rendering_settings.c b/libfonts_get_default_rendering_settings.c
index 21de5a9..ebdc51c 100644
--- a/libfonts_get_default_rendering_settings.c
+++ b/libfonts_get_default_rendering_settings.c
@@ -9,6 +9,12 @@ getn(const char *file_part1, size_t file_part1_len, const char *file_part2,
{
size_t file_part2_len = strlen(file_part2);
char *path;
+ int fd;
+ ssize_t len;
+ char *line, *buf = NULL;
+ size_t size = 0, off = 0, avail = 0;
+ char *value;
+ unsigned int found_fields = 0;
if (file_part1_len > SIZE_MAX - file_part2_len - 1)
goto enomem;
@@ -23,8 +29,80 @@ getn(const char *file_part1, size_t file_part1_len, const char *file_part2,
memcpy(path, file_part1, file_part1_len);
memcpy(&path[file_part1_len], file_part2, file_part2_len + 1);
- /* TODO (use LIST_RENDERING_SETTINGS) */
+open_again:
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ switch (errno) {
+ case EINTR:
+ goto open_again;
+ case EMFILE:
+ case ENFILE:
+ case ENOMEM:
+ case ENOSPC:
+ free(path);
+ return -1;
+ case EFBIG:
+ case EOVERFLOW:
+ case EISDIR:
+ case ELOOP:
+ case ENODEV:
+ case ENOTDIR:
+ case ENXIO:
+ /* TODO print warning using `ctx` */
+ goto out;
+ default:
+ goto out;
+ }
+ }
+
+ for (;;) {
+ len = libfonts_getline__(fd, &line, &buf, &size, &off, &avail);
+ if (len < 0) {
+ if (errno == EINTR)
+ continue;
+ free(buf);
+ free(path);
+ close(fd);
+ return -1;
+ }
+ if (!len)
+ break;
+ line[len -= 1] = '\0';
+
+ while (isblank(*line))
+ line++;
+ if (!*line || *line == '#')
+ continue;
+ while (len && isblank(line[len - 1]))
+ len -= 1;
+ line[len] = '\0';
+
+ value = libfonts_confsplit__(line);
+ if (!value) {
+ /* TODO warning */
+ continue;
+ }
+
+#define X(INDEX, CONFNAME, CNAME, DEFVAL, PARSER)\
+ if (!strcmp(line, CONFNAME)) {\
+ if (found_fields & (1U << INDEX)) {\
+ /* TODO warning */\
+ }\
+ found_fields |= (1U << INDEX);\
+ if (!PARSER(&settings->CNAME, value)) {\
+ /* TODO warning */\
+ }\
+ } else
+ LIST_RENDERING_SETTINGS(X,) {
+ /* TODO warning */
+ }
+#undef X
+ }
+ free(buf);
+ close(fd);
+
+out:
free(path);
return 1;
}
@@ -47,7 +125,7 @@ libfonts_get_default_rendering_settings(struct libfonts_rendering_settings *sett
size_t len;
if (settings) {
-#define X(CONFNAME, CNAME, DEFVAL) settings->CNAME = DEFVAL
+#define X(INDEX, CONFNAME, CNAME, DEFVAL, PARSER) settings->CNAME = DEFVAL
LIST_RENDERING_SETTINGS(X, ;);
#undef X
}
diff --git a/libfonts_get_output_rendering_settings.c b/libfonts_get_output_rendering_settings.c
index f634550..2cecf3c 100644
--- a/libfonts_get_output_rendering_settings.c
+++ b/libfonts_get_output_rendering_settings.c
@@ -9,6 +9,15 @@ getn(const char *file_part1, size_t file_part1_len, const char *file_part2,
{
size_t file_part2_len = strlen(file_part2);
char *path;
+ int fd;
+ ssize_t len;
+ char *line, *buf = NULL;
+ size_t size = 0, off = 0, avail = 0;
+ int found = 0;
+ int in_the_section = 0;
+ int in_a_section = 0;
+ char *value;
+ unsigned int found_fields = 0;
if (file_part1_len > SIZE_MAX - file_part2_len - 1)
goto enomem;
@@ -23,12 +32,101 @@ getn(const char *file_part1, size_t file_part1_len, const char *file_part2,
memcpy(path, file_part1, file_part1_len);
memcpy(&path[file_part1_len], file_part2, file_part2_len + 1);
- /* TODO aliases should be declarable above the first "[$name]" */
- /* TODO look for "[$name]" */
- /* TODO (use LIST_RENDERING_SETTINGS) */
+open_again:
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ switch (errno) {
+ case EINTR:
+ goto open_again;
+ case EMFILE:
+ case ENFILE:
+ case ENOMEM:
+ case ENOSPC:
+ free(path);
+ return -1;
+ case EFBIG:
+ case EOVERFLOW:
+ case EISDIR:
+ case ELOOP:
+ case ENODEV:
+ case ENOTDIR:
+ case ENXIO:
+ /* TODO print warning using `ctx` */
+ goto out;
+ default:
+ goto out;
+ }
+ }
+
+ for (;;) {
+ len = libfonts_getline__(fd, &line, &buf, &size, &off, &avail);
+ if (len < 0) {
+ if (errno == EINTR)
+ continue;
+ free(buf);
+ free(path);
+ close(fd);
+ return -1;
+ }
+ if (!len)
+ break;
+ line[len -= 1] = '\0';
+
+ while (isblank(*line)) {
+ line++;
+ len--;
+ }
+ if (!*line || *line == '#')
+ continue;
+ while (len && isblank(line[len - 1]))
+ len -= 1;
+ line[len] = '\0';
+
+ if (line[0] == '[' && line[len - 1] == ']') {
+ in_a_section = 1;
+ line = &line[1];
+ len -= 2;
+ line[len] = '\0';
+ found |= in_the_section = !strcmp(line, name);
+ found_fields = 0;
+
+ } else if (!in_a_section) {
+ value = libfonts_confsplit__(line);
+ if (!value) {
+ /* TODO warning */
+ continue;
+ }
+ /* TODO aliases should be declarable above the first "[%s]" */
+
+ } else if (in_the_section) {
+ value = libfonts_confsplit__(line);
+ if (!value) {
+ /* TODO warning */
+ continue;
+ }
+#define X(INDEX, CONFNAME, CNAME, DEFVAL, PARSER)\
+ if (!strcmp(line, CONFNAME)) {\
+ if (found_fields & (1U << INDEX)) {\
+ /* TODO warning */\
+ }\
+ found_fields |= (1U << INDEX);\
+ if (!PARSER(&settings->CNAME, value)) {\
+ /* TODO warning */\
+ }\
+ } else
+ LIST_RENDERING_SETTINGS(X,) {
+ /* TODO warning */
+ }
+#undef X
+ }
+ }
+
+ free(buf);
+ close(fd);
+out:
free(path);
- return 1;
+ return found;
}
static int
@@ -54,7 +152,7 @@ libfonts_get_output_rendering_settings(struct libfonts_rendering_settings *setti
}
if (settings) {
-#define X(CONFNAME, CNAME, DEFVAL) settings->CNAME = DEFVAL
+#define X(INDEX, CONFNAME, CNAME, DEFVAL, PARSER) settings->CNAME = DEFVAL
LIST_RENDERING_SETTINGS(X, ;);
#undef X
}
diff --git a/libfonts_getenv__.c b/libfonts_getenv__.c
index d998337..8ea0ce6 100644
--- a/libfonts_getenv__.c
+++ b/libfonts_getenv__.c
@@ -1,5 +1,6 @@
/* See LICENSE file for copyright and license details. */
#include "common.h"
+#ifndef TEST
const char *
@@ -28,3 +29,16 @@ ok:
return *envp;
return ctx->ignore_process_environ ? NULL : getenv(name);
}
+
+
+#else
+
+
+int
+main(void)
+{
+ return 0; /* TODO add test */
+}
+
+
+#endif
diff --git a/libfonts_gethome__.c b/libfonts_gethome__.c
index 902029f..f05dbfb 100644
--- a/libfonts_gethome__.c
+++ b/libfonts_gethome__.c
@@ -1,5 +1,6 @@
/* See LICENSE file for copyright and license details. */
#include "common.h"
+#ifndef TEST
char *
@@ -38,3 +39,16 @@ libfonts_gethome__(struct libfonts_context *ctx)
free(buf);
return ret;
}
+
+
+#else
+
+
+int
+main(void)
+{
+ return 0; /* TODO add test */
+}
+
+
+#endif
diff --git a/libfonts_getline__.c b/libfonts_getline__.c
new file mode 100644
index 0000000..58b1adc
--- /dev/null
+++ b/libfonts_getline__.c
@@ -0,0 +1,65 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+/* alternative to getline(3) that does not have a line length limit */
+
+ssize_t
+libfonts_getline__(int fd, char **linep, char **bufp, size_t *sizep, size_t *offp, size_t *availp)
+{
+ size_t len, size;
+ ssize_t r;
+ char *new;
+
+ for (;;) {
+ for (len = 0; *offp + len < *availp; len++) {
+ if ((*bufp)[*offp + len] == '\n') {
+ *linep = &(*bufp)[*offp];
+ *offp += len += 1;
+ return (ssize_t)len;
+ }
+ }
+
+ if (*offp) {
+ memmove(&(*bufp)[0], &(*bufp)[*offp], *availp -= *offp);
+ *offp = 0;
+ }
+
+ if (*availp == *sizep) {
+ if (*sizep > SIZE_MAX - 128)
+ goto enomem;
+ size = *sizep + 128;
+ new = realloc(*bufp, size);
+ if (!new) {
+ enomem:
+ errno = ENOMEM;
+ return -1;
+ }
+ *bufp = new;
+ *sizep = size;
+ }
+ r = read(fd, &(*bufp)[*availp], *sizep - *availp);
+ if (r <= 0) {
+ if (r < 0)
+ return -1;
+ *linep = *bufp;
+ *offp = *availp;
+ return (ssize_t)*availp;
+ }
+ *availp += (size_t)r;
+ }
+}
+
+
+#else
+
+
+int
+main(void)
+{
+ return 0; /* TODO add test */
+}
+
+
+#endif
diff --git a/libfonts_parse_aa__.c b/libfonts_parse_aa__.c
new file mode 100644
index 0000000..5946b1c
--- /dev/null
+++ b/libfonts_parse_aa__.c
@@ -0,0 +1,51 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+#define LIST_ANTIALIASINGS(X)\
+ X(LIBFONTS_ANTIALIASING_UNSPECIFIED, "unspecified")\
+ X(LIBFONTS_ANTIALIASING_NONE, "none")\
+ X(LIBFONTS_ANTIALIASING_NONE, "aliased")\
+ X(LIBFONTS_ANTIALIASING_GREYSCALE, "greyscale")\
+ X(LIBFONTS_ANTIALIASING_GREYSCALE, "grayscale")\
+ X(LIBFONTS_ANTIALIASING_GREYSCALE, "grey")\
+ X(LIBFONTS_ANTIALIASING_GREYSCALE, "gray")\
+ X(LIBFONTS_ANTIALIASING_GREYSCALE, "antialiased")\
+ X(LIBFONTS_ANTIALIASING_GREYSCALE_FORCED, "greyscale!")\
+ X(LIBFONTS_ANTIALIASING_GREYSCALE_FORCED, "grayscale!")\
+ X(LIBFONTS_ANTIALIASING_GREYSCALE_FORCED, "grey!")\
+ X(LIBFONTS_ANTIALIASING_GREYSCALE_FORCED, "gray!")\
+ X(LIBFONTS_ANTIALIASING_GREYSCALE_FORCED, "antialiased!")\
+ X(LIBFONTS_ANTIALIASING_SUBPIXEL, "subpixel")\
+ X(LIBFONTS_ANTIALIASING_SUBPIXEL, "glitter")\
+ X(LIBFONTS_ANTIALIASING_SUBPIXEL_FORCED, "subpixel!")\
+ X(LIBFONTS_ANTIALIASING_SUBPIXEL_FORCED, "glitter!")
+
+int
+libfonts_parse_aa__(enum libfonts_antialiasing *outp, const char *value)
+{
+#define X(C, S)\
+ if (!strcasecmp(value, S)) {\
+ *outp = C;\
+ } else
+ LIST_ANTIALIASINGS(X) {
+ return 0;
+ }
+#undef X
+ return 1;
+
+}
+
+
+#else
+
+
+int
+main(void)
+{
+ return 0; /* TODO add test */
+}
+
+
+#endif
diff --git a/libfonts_parse_double__.c b/libfonts_parse_double__.c
new file mode 100644
index 0000000..30fc61d
--- /dev/null
+++ b/libfonts_parse_double__.c
@@ -0,0 +1,23 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+int
+libfonts_parse_double__(double *outp, const char *value)
+{
+ return 0; /* TODO implement */
+}
+
+
+#else
+
+
+int
+main(void)
+{
+ return 0; /* TODO add test */
+}
+
+
+#endif
diff --git a/libfonts_parse_order__.c b/libfonts_parse_order__.c
new file mode 100644
index 0000000..53b4aa4
--- /dev/null
+++ b/libfonts_parse_order__.c
@@ -0,0 +1,105 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+#define LIST_SUBPIXEL_ORDERS(X)\
+ X(LIBFONTS_SUBPIXEL_ORDER_UNKNOWN, "unknown")\
+ X(LIBFONTS_SUBPIXEL_ORDER_NONRGB, "non-rgb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_NONLINEAR, "non-linear")\
+ X(LIBFONTS_SUBPIXEL_ORDER_OTHER, "other")\
+ X(LIBFONTS_SUBPIXEL_ORDER_RGB, "rgb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_R_G_B, "r:g:b")\
+ X(LIBFONTS_SUBPIXEL_ORDER_R_G_B, "vrgb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BGR, "bgr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_B_G_R, "b:g:r")\
+ X(LIBFONTS_SUBPIXEL_ORDER_B_G_R, "vbgr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_GBR, "gbr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_G_B_R, "g:b:r")\
+ X(LIBFONTS_SUBPIXEL_ORDER_G_B_R, "vgbr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_RBG, "rbg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_R_B_G, "r:b:g")\
+ X(LIBFONTS_SUBPIXEL_ORDER_R_B_G, "vrbg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BRG, "brg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_B_R_G, "b:r:g")\
+ X(LIBFONTS_SUBPIXEL_ORDER_B_R_G, "vbrg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_GRB, "grb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_G_R_B, "g:r:b")\
+ X(LIBFONTS_SUBPIXEL_ORDER_G_R_B, "vgrb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_RR_GB, "rr:gb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_GR_BR, "gr:br")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BG_RR, "bg:rr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_RB_RG, "rb:rg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_RR_BG, "rr:bg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BR_GR, "br:gr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_GB_RR, "gb:rr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_RG_RB, "rg:rb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_GG_RB, "gg:rb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_RG_BG, "rg:bg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BR_GG, "br:gg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_GB_GR, "gb:gr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_GG_BR, "gg:br")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BG_RG, "bg:rg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_RB_GG, "rb:gg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_GR_GB, "gr:gb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BB_RG, "bb:rg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_RB_GB, "rb:gb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_GR_BB, "gr:bb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BG_BR, "bg:br")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BB_GR, "bb:gr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_GB_RB, "gb:rb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_RG_BB, "rg:bb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BR_BG, "br:bg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_RR_GB, "balanced rr:gb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_GR_BR, "balanced gr:br")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_BG_RR, "balanced bg:rr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_RB_RG, "balanced rb:rg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_RR_BG, "balanced rr:bg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_BR_GR, "balanced br:gr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_GB_RR, "balanced gb:rr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_RG_RB, "balanced rg:rb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_GG_RB, "balanced gg:rb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_RG_BG, "balanced rg:bg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_BR_GG, "balanced br:gg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_GB_GR, "balanced gb:gr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_GG_BR, "balanced gg:br")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_BG_RG, "balanced bg:rg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_RB_GG, "balanced rb:gg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_GR_GB, "balanced gr:gb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_BB_RG, "balanced bb:rg")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_RB_GB, "balanced rb:gb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_GR_BB, "balanced gr:bb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_BG_BR, "balanced bg:br")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_BB_GR, "balanced bb:gr")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_GB_RB, "balanced gb:rb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_RG_BB, "balanced rg:bb")\
+ X(LIBFONTS_SUBPIXEL_ORDER_BALANCED_BR_BG, "balanced br:bg")
+
+int
+libfonts_parse_order__(enum libfonts_subpixel_order *outp, const char *value)
+{
+#define X(C, S)\
+ if (!strcasecmp(value, S)) {\
+ *outp = C;\
+ } else
+ LIST_SUBPIXEL_ORDERS(X) {
+ *outp = LIBFONTS_SUBPIXEL_ORDER_OTHER;
+ return 0;
+ }
+#undef X
+ return 1;
+
+}
+
+
+#else
+
+
+int
+main(void)
+{
+ return 0; /* TODO add test */
+}
+
+
+#endif
diff --git a/libfonts_parse_uint32__.c b/libfonts_parse_uint32__.c
new file mode 100644
index 0000000..f87f19e
--- /dev/null
+++ b/libfonts_parse_uint32__.c
@@ -0,0 +1,36 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+int
+libfonts_parse_uint32__(uint32_t *outp, const char *value)
+{
+ uint32_t out = 0, digit;
+ value += *value == '+';
+ if (!*value)
+ return 0;
+ while (isdigit(*value)) {
+ digit = (*value & 15);
+ if (out > (UINT32_C(0xFFFFFFFF) - digit) / 10)
+ return 0;
+ out = out * 10 + digit;
+ }
+ if (*value)
+ return 0;
+ *outp = out;
+ return 1;
+}
+
+
+#else
+
+
+int
+main(void)
+{
+ return 0; /* TODO add test */
+}
+
+
+#endif