Mercurial > repos > blastem
view nuklear_ui/font_android.c @ 1925:039553703c20
Don't apply address and cd register changes to the 'live' registers until pending flag is cleared, but do preserve the upper address bits in the latch. Fixes regression in Overdrive 2 while preserving fix to Mona in 344 bytes
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 13 Apr 2020 20:43:25 -0700 |
parents | 78abbabfd58d |
children | 13abdc98379e c649bcc18487 |
line wrap: on
line source
#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; }