feat: Word Processor discovers fonts automatically (via 0:/fonts), UI fix
This commit is contained in:
@@ -128,6 +128,44 @@ static void wp_fit_ui_text(const char* src, char* out, int out_len, int max_w) {
|
||||
}
|
||||
}
|
||||
|
||||
// Truncate from the end with a trailing ".." so `src` fits in max_w pixels.
|
||||
// Used for labels (e.g. font names) where the start carries the meaning.
|
||||
static void wp_fit_ui_text_end(const char* src, char* out, int out_len, int max_w) {
|
||||
if (out_len <= 0) return;
|
||||
if (!src) { out[0] = '\0'; return; }
|
||||
|
||||
montauk::strncpy(out, src, out_len - 1);
|
||||
out[out_len - 1] = '\0';
|
||||
if (text_width(g_ui_font, out, fonts::UI_SIZE) <= max_w) return;
|
||||
|
||||
for (int keep = montauk::slen(src); keep > 0; keep--) {
|
||||
char candidate[256];
|
||||
if (keep > (int)sizeof(candidate) - 3) continue;
|
||||
montauk::memcpy(candidate, src, keep);
|
||||
candidate[keep] = '.';
|
||||
candidate[keep + 1] = '.';
|
||||
candidate[keep + 2] = '\0';
|
||||
if (text_width(g_ui_font, candidate, fonts::UI_SIZE) <= max_w) {
|
||||
montauk::strncpy(out, candidate, out_len - 1);
|
||||
out[out_len - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
out[0] = '\0';
|
||||
}
|
||||
|
||||
// Width of the font popup, sized to the longest discovered name (clamped) so
|
||||
// names display in full in the list even when the toolbar button is narrow.
|
||||
int wp_font_dropdown_width() {
|
||||
int w = 110;
|
||||
for (int i = 0; i < wp_font_count(); i++) {
|
||||
int tw = text_width(g_ui_font, wp_font_name(i), fonts::UI_SIZE) + 24;
|
||||
if (tw > w) w = tw;
|
||||
}
|
||||
if (w > 260) w = 260;
|
||||
return w;
|
||||
}
|
||||
|
||||
static ParagraphStyle* wp_current_paragraph_style(WordProcessorState* wp) {
|
||||
if (wp->paragraph_count <= 0) {
|
||||
static ParagraphStyle fallback = { PARA_ALIGN_LEFT, PARA_LIST_NONE, 100, PARA_DIVIDER_NONE, 0, 0, 0, 0 };
|
||||
@@ -247,14 +285,18 @@ void wp_render() {
|
||||
Color italic_bg = (wp->cur_flags & STYLE_ITALIC) ? btn_active : btn_bg;
|
||||
c.fill_rounded_rect(WP_BTN_ITALIC_X, 6, 24, 24, 3, italic_bg);
|
||||
{
|
||||
TrueTypeFont* italic_font = wp_get_font(FONT_ROBOTO, STYLE_ITALIC);
|
||||
TrueTypeFont* italic_font = wp_get_font(wp_default_font_id(), STYLE_ITALIC);
|
||||
draw_text(c, italic_font ? italic_font : g_ui_font, WP_BTN_ITALIC_X + 9, 8, "I", colors::TEXT_COLOR, fonts::UI_SIZE);
|
||||
}
|
||||
|
||||
c.fill_rounded_rect(WP_FONT_DD_X, 6, WP_FONT_DD_W, 24, 3, btn_bg);
|
||||
wp_draw_ui_text(c, WP_FONT_DD_X + 6, (WP_TOOLBAR_H - sfh) / 2,
|
||||
WP_FONT_NAMES[wp->cur_font_id < FONT_COUNT ? wp->cur_font_id : 0],
|
||||
colors::TEXT_COLOR);
|
||||
{
|
||||
char font_fit[WP_FONT_NAME_MAX + 4];
|
||||
wp_fit_ui_text_end(wp_font_name(wp->cur_font_id), font_fit, sizeof(font_fit),
|
||||
WP_FONT_DD_W - 12);
|
||||
wp_draw_ui_text(c, WP_FONT_DD_X + 6, (WP_TOOLBAR_H - sfh) / 2,
|
||||
font_fit, colors::TEXT_COLOR);
|
||||
}
|
||||
|
||||
c.fill_rounded_rect(WP_SIZE_DD_X, 6, WP_SIZE_DD_W, 24, 3, btn_bg);
|
||||
{
|
||||
@@ -305,7 +347,7 @@ void wp_render() {
|
||||
c.fill_rounded_rect(WP_BTN_SECTION_X, 6, 24, 24, 3, special_bg);
|
||||
{
|
||||
char section[2] = { (char)0xA7, '\0' };
|
||||
TrueTypeFont* font = wp_get_font(FONT_ROBOTO, 0);
|
||||
TrueTypeFont* font = wp_get_font(wp_default_font_id(), 0);
|
||||
draw_text(c, font ? font : g_ui_font, WP_BTN_SECTION_X + 6, 8, section, colors::TEXT_COLOR, fonts::UI_SIZE);
|
||||
}
|
||||
|
||||
@@ -573,12 +615,12 @@ void wp_render() {
|
||||
if (cur_para->divider_type != PARA_DIVIDER_NONE) {
|
||||
snprintf(status_left, sizeof(status_left), " %s%s | %s %dpt | Divider: %s | %d%%",
|
||||
name, wp->modified ? " *" : "",
|
||||
WP_FONT_NAMES[wp->cur_font_id < FONT_COUNT ? wp->cur_font_id : 0], (int)wp->cur_size,
|
||||
wp_font_name(wp->cur_font_id), (int)wp->cur_size,
|
||||
wp_divider_label(cur_para->divider_type), (int)cur_para->line_spacing);
|
||||
} else {
|
||||
snprintf(status_left, sizeof(status_left), " %s%s | %s %dpt | %s | %s | %d%%",
|
||||
name, wp->modified ? " *" : "",
|
||||
WP_FONT_NAMES[wp->cur_font_id < FONT_COUNT ? wp->cur_font_id : 0], (int)wp->cur_size,
|
||||
wp_font_name(wp->cur_font_id), (int)wp->cur_size,
|
||||
wp_align_label(cur_para->align), wp_list_label(cur_para->list_type),
|
||||
(int)cur_para->line_spacing);
|
||||
}
|
||||
@@ -599,15 +641,17 @@ void wp_render() {
|
||||
if (wp->font_dropdown_open) {
|
||||
int dx = WP_FONT_DD_X;
|
||||
int dy = WP_TOOLBAR_H;
|
||||
int dw = 110;
|
||||
int dh = FONT_COUNT * 26 + 4;
|
||||
int dw = wp_font_dropdown_width();
|
||||
int dh = wp_font_count() * 26 + 4;
|
||||
c.fill_rect(dx, dy, dw, dh, colors::MENU_BG);
|
||||
c.rect(dx, dy, dw, dh, colors::BORDER);
|
||||
for (int i = 0; i < FONT_COUNT; i++) {
|
||||
for (int i = 0; i < wp_font_count(); i++) {
|
||||
int iy = dy + 2 + i * 26;
|
||||
if (i == wp->cur_font_id)
|
||||
c.fill_rect(dx + 2, iy, dw - 4, 24, colors::MENU_HOVER);
|
||||
wp_draw_ui_text(c, dx + 8, iy + (24 - sfh) / 2, WP_FONT_NAMES[i], colors::TEXT_COLOR);
|
||||
char item_fit[WP_FONT_NAME_MAX + 4];
|
||||
wp_fit_ui_text_end(wp_font_name(i), item_fit, sizeof(item_fit), dw - 16);
|
||||
wp_draw_ui_text(c, dx + 8, iy + (24 - sfh) / 2, item_fit, colors::TEXT_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -668,7 +712,7 @@ void wp_render() {
|
||||
int dy = WP_TOOLBAR_H;
|
||||
int dw = WP_SPECIAL_CHAR_FLYOUT_W;
|
||||
int dh = WP_SPECIAL_CHAR_OPTION_COUNT * WP_SPECIAL_CHAR_ROW_H + 4;
|
||||
TrueTypeFont* glyph_font = wp_get_font(FONT_ROBOTO, 0);
|
||||
TrueTypeFont* glyph_font = wp_get_font(wp_default_font_id(), 0);
|
||||
c.fill_rect(dx, dy, dw, dh, colors::MENU_BG);
|
||||
c.rect(dx, dy, dw, dh, colors::BORDER);
|
||||
for (int i = 0; i < WP_SPECIAL_CHAR_OPTION_COUNT; i++) {
|
||||
|
||||
Reference in New Issue
Block a user