Selection color from accent color
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
91
src/App.cpp
91
src/App.cpp
@@ -3,10 +3,10 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cmath>
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -66,8 +66,8 @@ struct SurroundingSlice {
|
|||||||
int anchor { 0 };
|
int anchor { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
auto clamp_surrounding_text(
|
auto clamp_surrounding_text(std::string const &text, int cursor, int anchor)
|
||||||
std::string const &text, int cursor, int anchor) -> SurroundingSlice
|
-> SurroundingSlice
|
||||||
{
|
{
|
||||||
int const size = static_cast<int>(text.size());
|
int const size = static_cast<int>(text.size());
|
||||||
cursor = std::clamp(cursor, 0, size);
|
cursor = std::clamp(cursor, 0, size);
|
||||||
@@ -78,19 +78,17 @@ auto clamp_surrounding_text(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int window_start = std::max(0,
|
int window_start = std::max(0,
|
||||||
std::min(cursor, anchor)
|
std::min(cursor, anchor) - static_cast<int>(MAX_SURROUNDING_BYTES / 2));
|
||||||
- static_cast<int>(MAX_SURROUNDING_BYTES / 2));
|
|
||||||
int window_end = window_start + static_cast<int>(MAX_SURROUNDING_BYTES);
|
int window_end = window_start + static_cast<int>(MAX_SURROUNDING_BYTES);
|
||||||
int const max_pos = std::max(cursor, anchor);
|
int const max_pos = std::max(cursor, anchor);
|
||||||
if (window_end < max_pos) {
|
if (window_end < max_pos) {
|
||||||
window_end = max_pos;
|
window_end = max_pos;
|
||||||
window_start = std::max(0,
|
window_start
|
||||||
window_end - static_cast<int>(MAX_SURROUNDING_BYTES));
|
= std::max(0, window_end - static_cast<int>(MAX_SURROUNDING_BYTES));
|
||||||
}
|
}
|
||||||
if (window_end > size)
|
if (window_end > size)
|
||||||
window_end = size;
|
window_end = size;
|
||||||
if (window_end - window_start
|
if (window_end - window_start > static_cast<int>(MAX_SURROUNDING_BYTES)) {
|
||||||
> static_cast<int>(MAX_SURROUNDING_BYTES)) {
|
|
||||||
window_start = window_end - static_cast<int>(MAX_SURROUNDING_BYTES);
|
window_start = window_end - static_cast<int>(MAX_SURROUNDING_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,8 +355,8 @@ auto App::init_wayland() -> void
|
|||||||
|
|
||||||
static zwp_text_input_v3_listener text_input_listener {};
|
static zwp_text_input_v3_listener text_input_listener {};
|
||||||
{
|
{
|
||||||
auto ti_enter = [](void *data, zwp_text_input_v3 *, wl_surface *surface)
|
auto ti_enter
|
||||||
-> void {
|
= [](void *data, zwp_text_input_v3 *, wl_surface *surface) -> void {
|
||||||
auto *app = static_cast<App *>(data);
|
auto *app = static_cast<App *>(data);
|
||||||
bool const focused_surface
|
bool const focused_surface
|
||||||
= surface && surface == app->m_wayland.surface;
|
= surface && surface == app->m_wayland.surface;
|
||||||
@@ -375,7 +373,8 @@ auto App::init_wayland() -> void
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ti_leave = [](void *data, zwp_text_input_v3 *, wl_surface *) -> void {
|
auto ti_leave
|
||||||
|
= [](void *data, zwp_text_input_v3 *, wl_surface *) -> void {
|
||||||
auto *app = static_cast<App *>(data);
|
auto *app = static_cast<App *>(data);
|
||||||
app->m_ime.seat_focus = false;
|
app->m_ime.seat_focus = false;
|
||||||
app->m_ime.enabled = false;
|
app->m_ime.enabled = false;
|
||||||
@@ -386,8 +385,9 @@ auto App::init_wayland() -> void
|
|||||||
app->m_gui->ime_clear_preedit();
|
app->m_gui->ime_clear_preedit();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ti_preedit = [](void *data, zwp_text_input_v3 *, char const *text,
|
auto ti_preedit
|
||||||
int32_t cursor_begin, int32_t cursor_end) -> void {
|
= [](void *data, zwp_text_input_v3 *, char const *text,
|
||||||
|
int32_t cursor_begin, int32_t cursor_end) -> void {
|
||||||
auto *app = static_cast<App *>(data);
|
auto *app = static_cast<App *>(data);
|
||||||
auto &pending = app->m_ime.pending;
|
auto &pending = app->m_ime.pending;
|
||||||
pending.has_preedit = true;
|
pending.has_preedit = true;
|
||||||
@@ -396,8 +396,8 @@ auto App::init_wayland() -> void
|
|||||||
pending.cursor_end = cursor_end;
|
pending.cursor_end = cursor_end;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ti_commit = [](void *data, zwp_text_input_v3 *, char const *text)
|
auto ti_commit
|
||||||
-> void {
|
= [](void *data, zwp_text_input_v3 *, char const *text) -> void {
|
||||||
auto *app = static_cast<App *>(data);
|
auto *app = static_cast<App *>(data);
|
||||||
auto &pending = app->m_ime.pending;
|
auto &pending = app->m_ime.pending;
|
||||||
pending.has_commit = true;
|
pending.has_commit = true;
|
||||||
@@ -405,7 +405,7 @@ auto App::init_wayland() -> void
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto ti_delete = [](void *data, zwp_text_input_v3 *, uint32_t before,
|
auto ti_delete = [](void *data, zwp_text_input_v3 *, uint32_t before,
|
||||||
uint32_t after) -> void {
|
uint32_t after) -> void {
|
||||||
auto *app = static_cast<App *>(data);
|
auto *app = static_cast<App *>(data);
|
||||||
auto &pending = app->m_ime.pending;
|
auto &pending = app->m_ime.pending;
|
||||||
pending.has_delete = true;
|
pending.has_delete = true;
|
||||||
@@ -413,15 +413,16 @@ auto App::init_wayland() -> void
|
|||||||
pending.after = after;
|
pending.after = after;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ti_done = [](void *data, zwp_text_input_v3 *, uint32_t serial) -> void {
|
auto ti_done
|
||||||
|
= [](void *data, zwp_text_input_v3 *, uint32_t serial) -> void {
|
||||||
auto *app = static_cast<App *>(data);
|
auto *app = static_cast<App *>(data);
|
||||||
app->m_ime.pending_done = true;
|
app->m_ime.pending_done = true;
|
||||||
app->m_ime.pending_serial = serial;
|
app->m_ime.pending_serial = serial;
|
||||||
app->m_ime.surrounding_dirty = true;
|
app->m_ime.surrounding_dirty = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
text_input_listener = { ti_enter, ti_leave, ti_preedit, ti_commit,
|
text_input_listener
|
||||||
ti_delete, ti_done };
|
= { ti_enter, ti_leave, ti_preedit, ti_commit, ti_delete, ti_done };
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto ensure_text_input = +[](App *app) -> void {
|
static auto ensure_text_input = +[](App *app) -> void {
|
||||||
@@ -481,8 +482,8 @@ auto App::init_wayland() -> void
|
|||||||
app->m_wayland.kde_blur_mgr
|
app->m_wayland.kde_blur_mgr
|
||||||
= static_cast<org_kde_kwin_blur_manager *>(wl_registry_bind(
|
= static_cast<org_kde_kwin_blur_manager *>(wl_registry_bind(
|
||||||
registry, name, &org_kde_kwin_blur_manager_interface, 1));
|
registry, name, &org_kde_kwin_blur_manager_interface, 1));
|
||||||
} else if (std::strcmp(interface,
|
} else if (std::strcmp(
|
||||||
zwp_text_input_manager_v3_interface.name)
|
interface, zwp_text_input_manager_v3_interface.name)
|
||||||
== 0) {
|
== 0) {
|
||||||
app->m_wayland.text_input_mgr
|
app->m_wayland.text_input_mgr
|
||||||
= static_cast<zwp_text_input_manager_v3 *>(wl_registry_bind(
|
= static_cast<zwp_text_input_manager_v3 *>(wl_registry_bind(
|
||||||
@@ -588,15 +589,27 @@ void App::on_settings_changed(XdpSettings * /*self*/, char const *ns,
|
|||||||
char const *key, GVariant * /*value*/, gpointer data)
|
char const *key, GVariant * /*value*/, gpointer data)
|
||||||
{
|
{
|
||||||
auto *app = static_cast<App *>(data);
|
auto *app = static_cast<App *>(data);
|
||||||
if (g_strcmp0(ns, "org.freedesktop.appearance") == 0
|
if (g_strcmp0(ns, "org.freedesktop.appearance") == 0) {
|
||||||
&& g_strcmp0(key, "color-scheme") == 0) {
|
if (g_strcmp0(key, "color-scheme") == 0) {
|
||||||
guint v = xdp_settings_read_uint(app->m_xdp.settings,
|
guint v = xdp_settings_read_uint(app->m_xdp.settings,
|
||||||
"org.freedesktop.appearance", "color-scheme", NULL, NULL);
|
"org.freedesktop.appearance", "color-scheme", NULL, NULL);
|
||||||
|
|
||||||
if (v == 1)
|
if (v == 1)
|
||||||
app->m_active_theme = Theme::Dark;
|
app->m_active_theme = Theme::Dark;
|
||||||
else
|
else
|
||||||
app->m_active_theme = Theme::Light;
|
app->m_active_theme = Theme::Light;
|
||||||
|
} else if (g_strcmp0(key, "accent-color") == 0) {
|
||||||
|
auto val = xdp_settings_read_value(app->m_xdp.settings,
|
||||||
|
"org.freedesktop.appearance", "accent-color", NULL, NULL);
|
||||||
|
if (val) {
|
||||||
|
gdouble r, g, b;
|
||||||
|
g_variant_get(val, "(ddd)", &r, &g, &b);
|
||||||
|
app->m_accent_color.r = static_cast<u8>(r * 255);
|
||||||
|
app->m_accent_color.g = static_cast<u8>(g * 255);
|
||||||
|
app->m_accent_color.b = static_cast<u8>(b * 255);
|
||||||
|
g_variant_unref(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,6 +625,17 @@ auto App::init_theme_portal() -> void
|
|||||||
else
|
else
|
||||||
m_active_theme = Theme::Light;
|
m_active_theme = Theme::Light;
|
||||||
|
|
||||||
|
auto val = xdp_settings_read_value(m_xdp.settings,
|
||||||
|
"org.freedesktop.appearance", "accent-color", NULL, NULL);
|
||||||
|
if (val) {
|
||||||
|
gdouble r, g, b;
|
||||||
|
g_variant_get(val, "(ddd)", &r, &g, &b);
|
||||||
|
m_accent_color.r = static_cast<u8>(r * 255);
|
||||||
|
m_accent_color.g = static_cast<u8>(g * 255);
|
||||||
|
m_accent_color.b = static_cast<u8>(b * 255);
|
||||||
|
g_variant_unref(val);
|
||||||
|
}
|
||||||
|
|
||||||
g_signal_connect(
|
g_signal_connect(
|
||||||
m_xdp.settings, "changed", G_CALLBACK(on_settings_changed), this);
|
m_xdp.settings, "changed", G_CALLBACK(on_settings_changed), this);
|
||||||
}
|
}
|
||||||
@@ -828,8 +852,7 @@ auto App::process_pending_text_input() -> void
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_ime.pending.has_commit) {
|
if (m_ime.pending.has_commit) {
|
||||||
m_gui->ime_commit_text(
|
m_gui->ime_commit_text(*m_ime.bound_text, m_ime.pending.commit_text);
|
||||||
*m_ime.bound_text, m_ime.pending.commit_text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_ime.pending.has_preedit) {
|
if (m_ime.pending.has_preedit) {
|
||||||
@@ -880,8 +903,8 @@ auto App::update_text_input_state(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (auto info = m_gui->text_input_surrounding(id, text)) {
|
if (auto info = m_gui->text_input_surrounding(id, text)) {
|
||||||
auto slice = clamp_surrounding_text(
|
auto slice
|
||||||
info->text, info->cursor, info->anchor);
|
= clamp_surrounding_text(info->text, info->cursor, info->anchor);
|
||||||
if (m_ime.surrounding_dirty || slice.text != m_ime.last_surrounding
|
if (m_ime.surrounding_dirty || slice.text != m_ime.last_surrounding
|
||||||
|| slice.cursor != m_ime.last_cursor
|
|| slice.cursor != m_ime.last_cursor
|
||||||
|| slice.anchor != m_ime.last_anchor) {
|
|| slice.anchor != m_ime.last_anchor) {
|
||||||
|
|||||||
@@ -191,5 +191,7 @@ private:
|
|||||||
bool m_running { true };
|
bool m_running { true };
|
||||||
bool m_visible { true };
|
bool m_visible { true };
|
||||||
|
|
||||||
|
Color m_accent_color { 127, 127, 255, 255 };
|
||||||
|
|
||||||
int m_sfd { -1 };
|
int m_sfd { -1 };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -307,11 +307,11 @@ auto ImGui::text_input(std::size_t id, std::pmr::string &str, Rectangle rec,
|
|||||||
if (m_focused_id == 0)
|
if (m_focused_id == 0)
|
||||||
m_focused_id = id;
|
m_focused_id = id;
|
||||||
|
|
||||||
if (options.font_size > rec.height) {
|
if (style().font_size > rec.height) {
|
||||||
TraceLog(LOG_WARNING,
|
TraceLog(LOG_WARNING,
|
||||||
std::format("Text size for text input {} is bigger than height ({} "
|
std::format("Text size for text input {} is bigger than height ({} "
|
||||||
"> {}). Clipping will occur.",
|
"> {}). Clipping will occur.",
|
||||||
id, options.font_size, rec.height)
|
id, style().font_size, rec.height)
|
||||||
.c_str());
|
.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,7 +545,7 @@ auto ImGui::text_input(std::size_t id, std::pmr::string &str, Rectangle rec,
|
|||||||
&& (!state.preedit_text.empty() || !state.preedit_cursor_hidden);
|
&& (!state.preedit_text.empty() || !state.preedit_cursor_hidden);
|
||||||
|
|
||||||
if (m_font.has_value() && m_text_renderer) {
|
if (m_font.has_value() && m_text_renderer) {
|
||||||
int const font_px = static_cast<int>(options.font_size);
|
int const font_px = static_cast<int>(style().font_size);
|
||||||
std::string_view const prefix_view(str.data(), caret_byte);
|
std::string_view const prefix_view(str.data(), caret_byte);
|
||||||
prefix_metrics
|
prefix_metrics
|
||||||
= m_text_renderer->measure_text(*m_font, prefix_view, font_px);
|
= m_text_renderer->measure_text(*m_font, prefix_view, font_px);
|
||||||
@@ -616,21 +616,21 @@ auto ImGui::text_input(std::size_t id, std::pmr::string &str, Rectangle rec,
|
|||||||
DrawRectangleLinesEx(rec, 1.0f, border_col);
|
DrawRectangleLinesEx(rec, 1.0f, border_col);
|
||||||
|
|
||||||
float const text_top = rec.y + VERTICAL_PADDING;
|
float const text_top = rec.y + VERTICAL_PADDING;
|
||||||
float const baseline_y = text_top + options.font_size;
|
float const baseline_y = text_top + style().font_size;
|
||||||
float const max_caret_height
|
float const max_caret_height
|
||||||
= std::max(0.0f, rec.height - 2.0f * VERTICAL_PADDING);
|
= std::max(0.0f, rec.height - 2.0f * VERTICAL_PADDING);
|
||||||
float caret_height = options.font_size * (1.0f + CARET_DESCENT_FRACTION);
|
float caret_height = style().font_size * (1.0f + CARET_DESCENT_FRACTION);
|
||||||
caret_height = std::min(caret_height,
|
caret_height = std::min(caret_height,
|
||||||
max_caret_height > 0.0f ? max_caret_height : caret_height);
|
max_caret_height > 0.0f ? max_caret_height : caret_height);
|
||||||
if (caret_height <= 0.0f)
|
if (caret_height <= 0.0f)
|
||||||
caret_height = options.font_size;
|
caret_height = style().font_size;
|
||||||
float caret_top = baseline_y - options.font_size;
|
float caret_top = baseline_y - style().font_size;
|
||||||
float const min_top = rec.y + VERTICAL_PADDING;
|
float const min_top = rec.y + VERTICAL_PADDING;
|
||||||
float const max_top = rec.y + rec.height - VERTICAL_PADDING - caret_height;
|
float const max_top = rec.y + rec.height - VERTICAL_PADDING - caret_height;
|
||||||
caret_top = std::clamp(caret_top, min_top, max_top);
|
caret_top = std::clamp(caret_top, min_top, max_top);
|
||||||
float caret_bottom = caret_top + caret_height;
|
float caret_bottom = caret_top + caret_height;
|
||||||
float const desired_bottom
|
float const desired_bottom
|
||||||
= baseline_y + options.font_size * CARET_DESCENT_FRACTION;
|
= baseline_y + style().font_size * CARET_DESCENT_FRACTION;
|
||||||
if (caret_bottom < desired_bottom) {
|
if (caret_bottom < desired_bottom) {
|
||||||
float const adjust = desired_bottom - caret_bottom;
|
float const adjust = desired_bottom - caret_bottom;
|
||||||
caret_top = std::min(caret_top + adjust, max_top);
|
caret_top = std::min(caret_top + adjust, max_top);
|
||||||
@@ -650,12 +650,12 @@ auto ImGui::text_input(std::size_t id, std::pmr::string &str, Rectangle rec,
|
|||||||
BeginScissorMode(rec.x, rec.y, rec.width, rec.height);
|
BeginScissorMode(rec.x, rec.y, rec.width, rec.height);
|
||||||
{
|
{
|
||||||
if (m_font.has_value() && m_text_renderer) {
|
if (m_font.has_value() && m_text_renderer) {
|
||||||
int const font_px = static_cast<int>(options.font_size);
|
int const font_px = static_cast<int>(style().font_size);
|
||||||
Vector2 const base_pos {
|
Vector2 const base_pos {
|
||||||
rec.x + HORIZONTAL_PADDING - state.scroll_offset.x,
|
rec.x + HORIZONTAL_PADDING - state.scroll_offset.x,
|
||||||
baseline_y,
|
baseline_y,
|
||||||
};
|
};
|
||||||
Color const &text_color = options.text_color;
|
Color const &text_color = style().text_color;
|
||||||
std::string_view const left_view(str.data(), caret_byte);
|
std::string_view const left_view(str.data(), caret_byte);
|
||||||
std::string_view const right_view(
|
std::string_view const right_view(
|
||||||
str.data() + caret_byte, str.size() - caret_byte);
|
str.data() + caret_byte, str.size() - caret_byte);
|
||||||
@@ -679,10 +679,12 @@ auto ImGui::text_input(std::size_t id, std::pmr::string &str, Rectangle rec,
|
|||||||
selection_metrics.x,
|
selection_metrics.x,
|
||||||
caret_height,
|
caret_height,
|
||||||
};
|
};
|
||||||
Color const highlight { 120, 160, 255, 100 };
|
Color const highlight { style().selection_color };
|
||||||
DrawRectangleRec(sel_rect, highlight);
|
DrawRectangleRec(sel_rect, highlight);
|
||||||
}
|
}
|
||||||
Color const &preedit_color { options.preedit_color };
|
Color const &preedit_color { selection_metrics.x > 0.0f
|
||||||
|
? style().selection_text_color
|
||||||
|
: style().preedit_color };
|
||||||
m_text_renderer->draw_text(*m_font,
|
m_text_renderer->draw_text(*m_font,
|
||||||
std::string_view(
|
std::string_view(
|
||||||
state.preedit_text.data(), state.preedit_text.size()),
|
state.preedit_text.data(), state.preedit_text.size()),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <queue>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
@@ -14,12 +15,17 @@ constexpr float DEFAULT_FONT_SIZE { 24 };
|
|||||||
|
|
||||||
struct TextInputOptions {
|
struct TextInputOptions {
|
||||||
bool multiline { false };
|
bool multiline { false };
|
||||||
float font_size { DEFAULT_FONT_SIZE };
|
|
||||||
Color text_color { BLACK };
|
|
||||||
Color preedit_color { BLACK };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImGui {
|
struct ImGui {
|
||||||
|
struct Style {
|
||||||
|
float font_size { DEFAULT_FONT_SIZE };
|
||||||
|
Color text_color { BLACK };
|
||||||
|
Color preedit_color { BLACK };
|
||||||
|
Color selection_color { 127, 127, 255, 255 };
|
||||||
|
Color selection_text_color { WHITE };
|
||||||
|
};
|
||||||
|
|
||||||
ImGui(std::shared_ptr<TextRenderer> text_renderer);
|
ImGui(std::shared_ptr<TextRenderer> text_renderer);
|
||||||
|
|
||||||
ImGui(ImGui const &) = delete;
|
ImGui(ImGui const &) = delete;
|
||||||
@@ -61,6 +67,14 @@ struct ImGui {
|
|||||||
|
|
||||||
void set_font(FontHandle font);
|
void set_font(FontHandle font);
|
||||||
|
|
||||||
|
auto style() -> Style & { return m_styles.back(); }
|
||||||
|
auto push_style(Style const &style) -> Style &
|
||||||
|
{
|
||||||
|
m_styles.push(style);
|
||||||
|
return m_styles.back();
|
||||||
|
}
|
||||||
|
auto push_style() -> Style & { return push_style(style()); }
|
||||||
|
|
||||||
[[nodiscard]] inline auto id(std::string_view const str) -> std::size_t
|
[[nodiscard]] inline auto id(std::string_view const str) -> std::size_t
|
||||||
{
|
{
|
||||||
std::hash<std::string_view> hasher;
|
std::hash<std::string_view> hasher;
|
||||||
@@ -90,6 +104,8 @@ private:
|
|||||||
bool m_ctrl {};
|
bool m_ctrl {};
|
||||||
bool m_shift {};
|
bool m_shift {};
|
||||||
|
|
||||||
|
std::queue<Style> m_styles { { Style {} } };
|
||||||
|
|
||||||
std::optional<FontHandle> m_font {};
|
std::optional<FontHandle> m_font {};
|
||||||
std::shared_ptr<TextRenderer> m_text_renderer {};
|
std::shared_ptr<TextRenderer> m_text_renderer {};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,9 +39,9 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr int kAtlasDimension = 1024;
|
constexpr int ATLAS_DIMENSION = 1024;
|
||||||
constexpr int kAtlasPadding = 2;
|
constexpr int ATLAS_PADDING = 2;
|
||||||
constexpr float kDefaultEmScale = 48.0f;
|
constexpr float DEFAULT_EM_SCALE = 48.0f;
|
||||||
|
|
||||||
constexpr float hb_to_em(hb_position_t value, unsigned upem)
|
constexpr float hb_to_em(hb_position_t value, unsigned upem)
|
||||||
{
|
{
|
||||||
@@ -143,8 +143,8 @@ auto TextRenderer::flush_font(FontRuntime &rt, FontData &fd) -> void
|
|||||||
{
|
{
|
||||||
rt.glyph_cache.clear();
|
rt.glyph_cache.clear();
|
||||||
fd.glyphs.clear();
|
fd.glyphs.clear();
|
||||||
rt.pen_x = kAtlasPadding;
|
rt.pen_x = ATLAS_PADDING;
|
||||||
rt.pen_y = kAtlasPadding;
|
rt.pen_y = ATLAS_PADDING;
|
||||||
rt.row_height = 0;
|
rt.row_height = 0;
|
||||||
if (fd.atlas_img.data)
|
if (fd.atlas_img.data)
|
||||||
ImageClearBackground(&fd.atlas_img, BLANK);
|
ImageClearBackground(&fd.atlas_img, BLANK);
|
||||||
@@ -156,20 +156,20 @@ auto TextRenderer::allocate_region(FontRuntime &rt, FontData &fd, int width,
|
|||||||
int height) -> std::optional<std::pair<int, int>>
|
int height) -> std::optional<std::pair<int, int>>
|
||||||
{
|
{
|
||||||
(void)fd;
|
(void)fd;
|
||||||
int padded_w = width + kAtlasPadding;
|
int padded_w = width + ATLAS_PADDING;
|
||||||
if (padded_w > rt.atlas_width || height + kAtlasPadding > rt.atlas_height)
|
if (padded_w > rt.atlas_width || height + ATLAS_PADDING > rt.atlas_height)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
if (rt.pen_x + padded_w > rt.atlas_width) {
|
if (rt.pen_x + padded_w > rt.atlas_width) {
|
||||||
rt.pen_x = kAtlasPadding;
|
rt.pen_x = ATLAS_PADDING;
|
||||||
rt.pen_y += rt.row_height;
|
rt.pen_y += rt.row_height;
|
||||||
rt.row_height = 0;
|
rt.row_height = 0;
|
||||||
}
|
}
|
||||||
if (rt.pen_y + height + kAtlasPadding > rt.atlas_height)
|
if (rt.pen_y + height + ATLAS_PADDING > rt.atlas_height)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
int x = rt.pen_x;
|
int x = rt.pen_x;
|
||||||
int y = rt.pen_y;
|
int y = rt.pen_y;
|
||||||
rt.pen_x += padded_w;
|
rt.pen_x += padded_w;
|
||||||
rt.row_height = std::max(rt.row_height, height + kAtlasPadding);
|
rt.row_height = std::max(rt.row_height, height + ATLAS_PADDING);
|
||||||
return std::pair { x, y };
|
return std::pair { x, y };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,8 +212,8 @@ auto TextRenderer::generate_glyph(FontRuntime &rt, FontData &fd,
|
|||||||
int bmp_h = std::max(
|
int bmp_h = std::max(
|
||||||
1, static_cast<int>(std::ceil(height_em * scale + 2.0 * rt.px_range)));
|
1, static_cast<int>(std::ceil(height_em * scale + 2.0 * rt.px_range)));
|
||||||
|
|
||||||
if (bmp_w + kAtlasPadding > rt.atlas_width
|
if (bmp_w + ATLAS_PADDING > rt.atlas_width
|
||||||
|| bmp_h + kAtlasPadding > rt.atlas_height) {
|
|| bmp_h + ATLAS_PADDING > rt.atlas_height) {
|
||||||
TraceLog(LOG_WARNING, "Glyph %u bitmap %dx%d exceeds atlas %dx%d",
|
TraceLog(LOG_WARNING, "Glyph %u bitmap %dx%d exceeds atlas %dx%d",
|
||||||
glyph_index, bmp_w, bmp_h, rt.atlas_width, rt.atlas_height);
|
glyph_index, bmp_w, bmp_h, rt.atlas_width, rt.atlas_height);
|
||||||
GlyphCacheEntry too_large {};
|
GlyphCacheEntry too_large {};
|
||||||
@@ -542,13 +542,13 @@ auto TextRenderer::load_single_font(std::filesystem::path const &path)
|
|||||||
|
|
||||||
auto runtime = std::make_unique<FontRuntime>();
|
auto runtime = std::make_unique<FontRuntime>();
|
||||||
runtime->face = face;
|
runtime->face = face;
|
||||||
runtime->atlas_width = kAtlasDimension;
|
runtime->atlas_width = ATLAS_DIMENSION;
|
||||||
runtime->atlas_height = kAtlasDimension;
|
runtime->atlas_height = ATLAS_DIMENSION;
|
||||||
runtime->pen_x = kAtlasPadding;
|
runtime->pen_x = ATLAS_PADDING;
|
||||||
runtime->pen_y = kAtlasPadding;
|
runtime->pen_y = ATLAS_PADDING;
|
||||||
runtime->row_height = 0;
|
runtime->row_height = 0;
|
||||||
runtime->px_range = 0.05; // kDefaultPxRange;
|
runtime->px_range = 0.05; // kDefaultPxRange;
|
||||||
runtime->em_scale = kDefaultEmScale;
|
runtime->em_scale = DEFAULT_EM_SCALE;
|
||||||
runtime->frame_stamp = 0;
|
runtime->frame_stamp = 0;
|
||||||
runtime->units_per_em
|
runtime->units_per_em
|
||||||
= static_cast<unsigned>(face->units_per_EM ? face->units_per_EM : 2048);
|
= static_cast<unsigned>(face->units_per_EM ? face->units_per_EM : 2048);
|
||||||
|
|||||||
@@ -34,6 +34,12 @@ auto App::tick() -> void
|
|||||||
|
|
||||||
{
|
{
|
||||||
assert(m_gui);
|
assert(m_gui);
|
||||||
|
|
||||||
|
m_gui->style().preedit_color = theme().foreground_preedit;
|
||||||
|
m_gui->style().text_color = theme().foreground;
|
||||||
|
m_gui->style().selection_color = m_accent_color;
|
||||||
|
m_gui->style().selection_text_color = WHITE;
|
||||||
|
|
||||||
u32 rune { 0 };
|
u32 rune { 0 };
|
||||||
if (!m_kbd.typing.empty()) {
|
if (!m_kbd.typing.empty()) {
|
||||||
rune = m_kbd.typing.back();
|
rune = m_kbd.typing.back();
|
||||||
@@ -47,8 +53,7 @@ auto App::tick() -> void
|
|||||||
static_cast<float>(GetScreenWidth()),
|
static_cast<float>(GetScreenWidth()),
|
||||||
static_cast<float>(GetScreenHeight()),
|
static_cast<float>(GetScreenHeight()),
|
||||||
};
|
};
|
||||||
auto result = m_gui->text_input(1, text_input_data, input_rect,
|
auto result = m_gui->text_input(1, text_input_data, input_rect);
|
||||||
{ .text_color = theme().foreground });
|
|
||||||
if (result.test(1))
|
if (result.test(1))
|
||||||
m_ime.surrounding_dirty = true;
|
m_ime.surrounding_dirty = true;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user