summaryrefslogtreecommitdiff
path: root/nuklear_ui
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2019-04-14 23:37:11 -0700
committerMichael Pavone <pavone@retrodev.com>2019-04-14 23:37:11 -0700
commit05af6e2720d03b538e64a73a84af1f4c4f8ce762 (patch)
tree6b7d1d16ce7fa5ae14b40069fb6b6dc6bc9c374d /nuklear_ui
parentf56f65652e292022c1a0fadb3807a7792468f267 (diff)
Get Android build working again and update for SDL 2.0.7 (last version to support older versions of Android)
Diffstat (limited to 'nuklear_ui')
-rw-r--r--nuklear_ui/font_android.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/nuklear_ui/font_android.c b/nuklear_ui/font_android.c
new file mode 100644
index 0000000..1ef4915
--- /dev/null
+++ b/nuklear_ui/font_android.c
@@ -0,0 +1,194 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include "../util.h"
+#include "../paths.h"
+#include "sfnt.h"
+
+typedef enum {
+ STATE_DEFAULT,
+ STATE_DECL,
+ STATE_COMMENT,
+ STATE_TAG,
+ STATE_PRE_ATTRIB,
+ STATE_ATTRIB,
+ STATE_PRE_VALUE,
+ STATE_VALUE
+} parse_state;
+
+#define DEFAULT_WEIGHT 400
+
+char *default_font_path(void)
+{
+ //Would probably be better to call into Java for this, but this should do for now
+ FILE *f = fopen("/system/etc/fonts.xml", "rb");
+ if (!f) {
+ return NULL;
+ }
+ long size = file_size(f);
+ char *font_xml = malloc(size+1);
+ if (size != fread(font_xml, 1, size, f)) {
+ free(font_xml);
+ fclose(f);
+ return NULL;
+ }
+ fclose(f);
+ font_xml[size] = 0;
+
+ char *last_tag = NULL, *last_attrib = NULL, *last_value = NULL;
+ uint8_t last_style_was_normal = 0;
+ char *capture_best = NULL;
+ char *best = NULL;
+ int best_weight_diff = INT_MAX;
+ int last_weight = INT_MAX;
+ parse_state state = STATE_DEFAULT;
+ for(char *cur = font_xml; *cur; ++cur) {
+ switch (state)
+ {
+ case STATE_DEFAULT:
+ if (*cur == '<' && cur[1]) {
+ cur++;
+ switch(*cur)
+ {
+ case '?':
+ state = STATE_DECL;
+ break;
+ case '!':
+ if (cur[1] == '-' && cur[2] == '-') {
+ state = STATE_COMMENT;
+ cur++;
+ } else {
+ debug_message("Invalid comment\n");
+ cur = font_xml + size - 1;
+ }
+ break;
+ default:
+ if (capture_best) {
+ cur[-1] = 0;
+ best = strip_ws(capture_best);
+ capture_best = NULL;
+ best_weight_diff = abs(last_weight - DEFAULT_WEIGHT);
+ debug_message("Found candidate %s with weight %d\n", best, last_weight);
+ }
+ state = STATE_TAG;
+ last_tag = cur;
+ last_attrib = NULL;
+ last_value = NULL;
+ last_weight = INT_MAX;
+ break;
+ }
+ }
+ break;
+ case STATE_DECL:
+ if (*cur == '?' && cur[1] == '>') {
+ cur++;
+ state = STATE_DEFAULT;
+ }
+ break;
+ case STATE_COMMENT:
+ if (*cur == '-' && cur[1] == '-' && cur[2] == '>') {
+ cur += 2;
+ state = STATE_DEFAULT;
+ }
+ break;
+ case STATE_TAG:
+ if (*cur == ' ' || *cur == '\t' || *cur == '\n' || *cur == '\r') {
+ *cur = 0;
+ state = STATE_PRE_ATTRIB;
+ } else if (*cur == '>') {
+ *cur = 0;
+ state = STATE_DEFAULT;
+ }
+ break;
+ case STATE_PRE_ATTRIB:
+ if (!(*cur == ' ' || *cur == '\t' || *cur == '\n' || *cur == '\r')) {
+ if (*cur == '>') {
+ state = STATE_DEFAULT;
+ if (last_style_was_normal && abs(last_weight - DEFAULT_WEIGHT) < best_weight_diff) {
+ capture_best = cur + 1;
+ } else if (best && !strcmp("/family", last_tag)) {
+ debug_message("found family close tag, stopping search\n");
+ cur = font_xml + size - 1;
+ }
+ } else {
+ last_attrib = cur;
+ state = STATE_ATTRIB;
+ }
+ }
+ break;
+ case STATE_ATTRIB:
+ if (*cur == '=') {
+ *cur = 0;
+ state = STATE_PRE_VALUE;
+ } else if (*cur == ' ' || *cur == '\t' || *cur == '\n' || *cur == '\r') {
+ *cur = 0;
+ }
+ break;
+ case STATE_PRE_VALUE:
+ if (*cur == '"') {
+ state = STATE_VALUE;
+ last_value = cur + 1;
+ }
+ break;
+ case STATE_VALUE:
+ if (*cur == '"') {
+ *cur = 0;
+ state = STATE_PRE_ATTRIB;
+ if (!strcmp("weight", last_attrib)) {
+ last_weight = atoi(last_value);
+ } else if (!strcmp("style", last_attrib)) {
+ last_style_was_normal = !strcmp("normal", last_value);
+ }
+ }
+ break;
+ }
+ }
+ if (best) {
+ best = path_append("/system/fonts", best);
+ }
+ free(font_xml);
+ return best;
+}
+
+static uint8_t *try_load_font(char *path, uint32_t *size_out)
+{
+ debug_message("Trying to load font %s\n", path);
+ FILE *f = fopen(path, "rb");
+ free(path);
+ if (!f) {
+ return NULL;
+ }
+ long size = file_size(f);
+ uint8_t *buffer = malloc(size);
+ if (size != fread(buffer, 1, size, f)) {
+ fclose(f);
+ return NULL;
+ }
+ fclose(f);
+ sfnt_container *sfnt = load_sfnt(buffer, size);
+ if (!sfnt) {
+ free(buffer);
+ return NULL;
+ }
+ return sfnt_flatten(sfnt->tables, size_out);
+}
+
+uint8_t *default_font(uint32_t *size_out)
+{
+ char *path = default_font_path();
+ if (!path) {
+ goto error;
+ }
+ uint8_t *ret = try_load_font(path, size_out);
+ if (ret) {
+ return ret;
+ }
+error:
+ //try some likely suspects if we failed to parse fonts.xml or failed to find the indicated font
+ ret = try_load_font("/system/fonts/Roboto-Regular.ttf", size_out);
+ if (!ret) {
+ ret = try_load_font("/system/fonts/DroidSans.ttf", size_out);
+ }
+ return ret;
+}