主题自适应配色 + 预览曲线连续配色 + 样式区复位按钮 + 均值滤波面板重做 + 面板缓存环带残留 + 调试层序 + 自由标记选取与性能
① 主题自适应(`Theme.cpp`):新增 `SrgbLuminance` / `ContrastRatio` / `EnsureContrast` /
`MixToLuminance` / `ThemeLaneBackground`;四套主题的结构色(gridWeak 1.30 / gridStrong 1.65 /
axisLine 2.10 / borderStrong 1.70)按底色自动校正,Solarised Light 逐位不变;网格叠底改用
`ThemeLaneBackground()`(4 处),深色主题下网格层与绘图区底色可辨。
② 派生预览曲线(`HighContrastDerived`)重写为**连续**方案:方向沿信号所在侧远离底色,
目标亮度 = max(与底色对比度 3.2, 信号亮度 ± 0.18),再按亮度平滑混色;调用点传入真实网格底色
(旧实现默认写死 Solarised Light 底色 ⇒ 深色主题永远选到更暗的那一侧、几乎看不见)。
③ 信号样式区「线宽 / 透明度」两行右侧新增**复位按钮**(`UiPaintResetIcon` 成为唯一实现,
菜单/弱峰面板/样式区共用同一套笔画);默认线宽统一到 `DefaultSignalLineWidth(finiteCount)`
(单点信号取 10.0)。按钮右边界与内容列对齐,内容列过窄时整列不显示。
④ 「均值滤波」面板重做:信号色叠底标题栏 + 复选框 + 展开三角 + 「均值点数 / 迭代次数」两行滑块
(点击数值可改滑块上限、右侧复位)+ 内容区滚动;新增 `MeanFilterItem::{maxPoints,maxIterations,
collapsed}` 与 `Lane::meanFilterScroll`,缓存键同步补全。
⑤ 浮动面板命中像素缓存时只贴**面板圆角形状之内**的像素(`CreateRoundRectRgn` 裁剪)并按本帧重画投影
⇒ 中键移视界后面板周围不再出现一圈旧波形。
⑥ 显示布局边界:每个浮动面板**独占一个绘制层**(按 `m_panelOrder` 递增),绘制侧
`UiSetTextLayer` 在同一循环内同步推进 ⇒ 下层面板的边框/文字不再画到上层面板上。
⑦ 自由标记:采样候选距离改为**二维欧氏距离**(单点信号不再在整幅宽度内吸住光标),
纵向光标画在鼠标位置、圆点落在真实采样点(新增 `FreeMarkerProbe::pointX`);
`MinorCellSparse` 只对胜出信号算一次;折线缓存容量改为 `max(64, 信号数×2)` 且查找改为
单键哈希 ⇒ MF4 的 285 信号合并网格中 `ProbeFreeMarker` 平均 0.11ms。
验证:`.preflight` 探针重建(`panelcheck` 71/71、`markercheck` 13/13、`ringcheck` 6/6,合计 90 条,
LTO 目标文件上复跑同样全绿);`make release` / `make debug` 零警告;产物 815,104 B。
文档:`agent_mem.md` 第十六轮(含补丁脚本与编码/行尾踩坑)。
This commit is contained in:
1 parent
71195c4c48
commit
bdd703b88b
24 files changed
+1815
-256
No files matched your search
@@ -355,6 +355,20 @@ namespace jdi
|
||||
void UiFillRoundRects(gd::Graphics& g, const std::vector<gd::RectF>& rects, float radius,
|
||||
std::uint32_t argb);
|
||||
|
||||
/**
|
||||
* @brief 绘制「还原 / 重置」图标(逆时针回环箭头)。
|
||||
*
|
||||
* **唯一实现**:弹出菜单标题栏的还原图标(`PopupMenu`)、弱峰调整面板每行滑块的复位控件、
|
||||
* 信号样式区「线宽 / 透明度」两行右侧的复位按钮全部调用它,因此同一语义在任何位置
|
||||
* 都是同一套笔画,任意 DPI 下都清晰(不依赖字体或图标资源)。
|
||||
*
|
||||
* @param [IN,OUT] g 绘图上下文。
|
||||
* @param [IN] rect 图标外接矩形(正方形;边长为 0 时不做任何绘制)。
|
||||
* @param [IN] argb 笔画颜色(0xAARRGGBB)。
|
||||
* @param [IN] scale DPI 缩放比例。
|
||||
*/
|
||||
void UiPaintResetIcon(gd::Graphics& g, const gd::RectF& rect, std::uint32_t argb, float scale);
|
||||
|
||||
} // namespace jdi
|
||||
|
||||
#endif // __PAINT_UTIL_HPP__
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include "Theme.hpp"
|
||||
#include "PaintUtil.hpp"
|
||||
|
||||
namespace jdi
|
||||
{
|
||||
@@ -63,36 +64,8 @@ namespace jdi
|
||||
*/
|
||||
inline void PaintResetIcon(gd::Graphics& g, const gd::RectF& rect, std::uint32_t color, float scale)
|
||||
{
|
||||
const float inset = 2.5f * scale;
|
||||
gd::RectF box(rect.X + inset, rect.Y + inset, rect.Width - inset * 2.0f,
|
||||
rect.Height - inset * 2.0f);
|
||||
if (box.Width <= 1.0f || box.Height <= 1.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
gd::Pen pen(gd::Color((color >> 24) & 0xFFu, (color >> 16) & 0xFFu, (color >> 8) & 0xFFu,
|
||||
color & 0xFFu),
|
||||
std::max(1.0f, 1.5f * scale));
|
||||
pen.SetStartCap(gd::LineCapRound);
|
||||
pen.SetEndCap(gd::LineCapRound);
|
||||
// 缺口留在右上角(从 300° 到 20° 处断开),与常见的"重置/刷新"图标一致。
|
||||
g.DrawArc(&pen, box.X, box.Y, box.Width, box.Height, 300.0f, 300.0f);
|
||||
|
||||
// 箭头:位于缺口末端(约 300° 方向),指向前进方向。
|
||||
const float cx = box.X + box.Width * 0.5f;
|
||||
const float cy = box.Y + box.Height * 0.5f;
|
||||
const float radius = box.Width * 0.5f;
|
||||
const float angle = 300.0f * 3.14159265f / 180.0f;
|
||||
const float tipX = cx + std::cos(angle) * radius;
|
||||
const float tipY = cy + std::sin(angle) * radius;
|
||||
const float size = std::max(2.5f, 3.2f * scale);
|
||||
gd::PointF arrow[3];
|
||||
arrow[0] = gd::PointF(tipX, tipY);
|
||||
arrow[1] = gd::PointF(tipX - size, tipY - size * 0.25f);
|
||||
arrow[2] = gd::PointF(tipX - size * 0.25f, tipY - size);
|
||||
gd::SolidBrush brush(gd::Color((color >> 24) & 0xFFu, (color >> 16) & 0xFFu,
|
||||
(color >> 8) & 0xFFu, color & 0xFFu));
|
||||
g.FillPolygon(&brush, arrow, 3);
|
||||
// 唯一实现见 `PaintUtil.hpp`(信号样式区的复位按钮、弱峰调整面板的复位控件共用)。
|
||||
UiPaintResetIcon(g, rect, color, scale);
|
||||
}
|
||||
} // namespace pmdetail
|
||||
|
||||
|
||||
@@ -74,6 +74,51 @@ namespace jdi
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 颜色的**相对亮度**(WCAG 2.x 定义:sRGB 线性化后按 0.2126/0.7152/0.0722 加权)。
|
||||
* @param [IN] argb 颜色值(只看 RGB 通道)。
|
||||
* @return 相对亮度,取值 0(黑)… 1(白)。
|
||||
*/
|
||||
double SrgbLuminance(std::uint32_t argb);
|
||||
|
||||
/**
|
||||
* @brief 两色之间的**对比度**(WCAG 2.x 定义:`(L1 + 0.05) / (L2 + 0.05)`)。
|
||||
* @param [IN] firstColor 第一色。
|
||||
* @param [IN] secondColor 第二色。
|
||||
* @return 对比度,取值 1(完全相同)… 21(黑白)。
|
||||
*/
|
||||
double ContrastRatio(std::uint32_t firstColor, std::uint32_t secondColor);
|
||||
|
||||
/**
|
||||
* @brief 保证前景色相对底色有**足够对比度**:不足时沿"远离底色"的方向混向黑/白。
|
||||
*
|
||||
* 用途:绘图区内部的网格线、时间轴等分线、分界线等原本按某一个主题手工调色的元素,
|
||||
* 必须跟着主题背景色自动适配(浅底上加深、深底上提亮),否则换到深色主题后
|
||||
* 网格线只剩几个色阶、几乎看不见。
|
||||
*
|
||||
* ⚠️ **已达标时逐位返回原色**:Solarised Light 的历史配色是人工调过的,
|
||||
* 只要它满足阈值就必须保持逐像素不变(避免"换主题修复"顺带改变默认主题观感)。
|
||||
*
|
||||
* @param [IN] background 底色(不透明)。
|
||||
* @param [IN] foreground 前景色(不透明)。
|
||||
* @param [IN] minRatio 期望的最小对比度(≥ 1,1 表示不限制)。
|
||||
* @return 满足阈值的颜色(RGB 不变、alpha = 0xFF)。
|
||||
*/
|
||||
std::uint32_t EnsureContrast(std::uint32_t background, std::uint32_t foreground, double minRatio);
|
||||
|
||||
/**
|
||||
* @brief 把颜色沿"亮度"插值到目标相对亮度(保持色相,二分求解混色比例)。
|
||||
*
|
||||
* 比"固定比例混向黑/白"更可控:调用方指定**目标亮度**,本函数负责求出混色量。
|
||||
* 目标亮度高于当前亮度时混向白、低于时混向黑;求解连续 ⇒ 输入微调时输出也连续
|
||||
*(不会在两个极端色之间跳变)。
|
||||
*
|
||||
* @param [IN] color 原色(不透明)。
|
||||
* @param [IN] targetLuminance 目标相对亮度(0…1)。
|
||||
* @return 亮度接近目标值的颜色(无法达到时取该方向上的极限)。
|
||||
*/
|
||||
std::uint32_t MixToLuminance(std::uint32_t color, double targetLuminance);
|
||||
|
||||
/**
|
||||
* @brief 界面主题色板(Solarised Light 派生)。
|
||||
*/
|
||||
@@ -152,6 +197,22 @@ namespace jdi
|
||||
*/
|
||||
void SetCurrentTheme(const Theme* theme);
|
||||
|
||||
/**
|
||||
* @brief 取「绘图区网格底色」——**网格叠底**(每条网格内部的底色)。
|
||||
*
|
||||
* 它与 `Theme::plotBg`(绘图区整体底色)分开:网格之外的时间轴/留白区用 `plotBg`,
|
||||
* 网格内部用本函数。当两者过于接近时,本函数会把网格底色**轻轻地**往远离绘图区
|
||||
* 底色的方向挪一点(仅供深色主题的 Solarised Dark 这类"两者完全同色"的情形),
|
||||
* 保证相邻网格仍能被分界线以外的底色层次区分开。
|
||||
*
|
||||
* ⚠️ 两者本来就有可辨识的亮度差时**逐位返回 `cardBg`**(Solarised Light / Light / Dark
|
||||
* 的默认观感不变)。
|
||||
*
|
||||
* @param [IN] theme 主题。
|
||||
* @return 网格底色(不透明)。
|
||||
*/
|
||||
std::uint32_t ThemeLaneBackground(const Theme& theme);
|
||||
|
||||
/**
|
||||
* @brief 获取波形默认配色表。
|
||||
* @param [OUT] count 配色数量输出。
|
||||
|
||||
@@ -676,4 +676,40 @@ namespace jdi
|
||||
g.ReleaseHDC(hdc);
|
||||
}
|
||||
|
||||
void UiPaintResetIcon(gd::Graphics& g, const gd::RectF& rect, std::uint32_t argb, float scale)
|
||||
{
|
||||
if (rect.Width <= 0.0f || rect.Height <= 0.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const float inset = 2.5f * scale;
|
||||
const gd::RectF box(rect.X + inset, rect.Y + inset, rect.Width - inset * 2.0f,
|
||||
rect.Height - inset * 2.0f);
|
||||
if (box.Width <= 1.0f || box.Height <= 1.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const gd::Color color = ToGdiColor(argb);
|
||||
gd::Pen pen(color, std::max(1.0f, 1.5f * scale));
|
||||
pen.SetStartCap(gd::LineCapRound);
|
||||
pen.SetEndCap(gd::LineCapRound);
|
||||
// 缺口留在右上角(从 300° 到 20° 处断开),与常见的"重置/刷新"图标一致。
|
||||
g.DrawArc(&pen, box.X, box.Y, box.Width, box.Height, 300.0f, 300.0f);
|
||||
|
||||
// 箭头:位于缺口末端(约 300° 方向),指向前进方向。
|
||||
const float cx = box.X + box.Width * 0.5f;
|
||||
const float cy = box.Y + box.Height * 0.5f;
|
||||
const float radius = box.Width * 0.5f;
|
||||
const float angle = 300.0f * 3.14159265f / 180.0f;
|
||||
const float tipX = cx + std::cos(angle) * radius;
|
||||
const float tipY = cy + std::sin(angle) * radius;
|
||||
const float size = std::max(2.5f, 3.2f * scale);
|
||||
gd::PointF arrow[3];
|
||||
arrow[0] = gd::PointF(tipX, tipY);
|
||||
arrow[1] = gd::PointF(tipX - size, tipY - size * 0.25f);
|
||||
arrow[2] = gd::PointF(tipX - size * 0.25f, tipY - size);
|
||||
gd::SolidBrush brush(color);
|
||||
g.FillPolygon(&brush, arrow, 3);
|
||||
}
|
||||
|
||||
} // namespace jdi
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "Theme.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
namespace jdi
|
||||
{
|
||||
|
||||
@@ -32,8 +35,32 @@ namespace jdi
|
||||
MakeArgb(kBase01), MakeArgb(kBase0),
|
||||
};
|
||||
|
||||
/** @brief 全局唯一主题实例。 */
|
||||
const Theme kSolarizedLight = []
|
||||
/**
|
||||
* @brief 把绘图区内部的"结构性"颜色按**底色**自动校正到足够对比(见 `EnsureContrast`)。
|
||||
*
|
||||
* 阈值(对比度)取"Solarised Light 现有配色刚好达标"的水位:
|
||||
* 该主题的历史配色是人工调过的,达标时 `EnsureContrast` 逐位返回原色 ⇒ 默认主题
|
||||
* **一个像素都不会变**;其它主题(尤其深色)则自动把网格线/时间轴/分界线提亮。
|
||||
*
|
||||
* | 字段 | 阈值 | Solarised Light 现状 |
|
||||
* | --- | ---: | ---: |
|
||||
* | `gridWeak`(网格主刻线 + 五等分线基色) | 1.30 | 约 1.38 |
|
||||
* | `gridStrong`(零线/加重线) | 1.65 | 约 1.80 |
|
||||
* | `axisLine`(时间轴、网格分界线、绘图区外框) | 2.10 | 约 2.43 |
|
||||
* | `borderStrong`(网格间分界线) | 1.70 | 约 2.43 |
|
||||
*/
|
||||
Theme NormalizePlotContrast(Theme theme)
|
||||
{
|
||||
const std::uint32_t plot = theme.plotBg | 0xFF000000u;
|
||||
theme.gridWeak = EnsureContrast(plot, theme.gridWeak | 0xFF000000u, 1.30);
|
||||
theme.gridStrong = EnsureContrast(plot, theme.gridStrong | 0xFF000000u, 1.65);
|
||||
theme.axisLine = EnsureContrast(plot, theme.axisLine | 0xFF000000u, 2.10);
|
||||
theme.borderStrong = EnsureContrast(plot, theme.borderStrong | 0xFF000000u, 1.70);
|
||||
return theme;
|
||||
}
|
||||
|
||||
/** @brief 全局唯一主题实例(Solarised Light;历史默认主题)。 */
|
||||
const Theme kSolarizedLight = NormalizePlotContrast([]
|
||||
{
|
||||
Theme theme;
|
||||
theme.windowBg = MakeArgb(kBase3);
|
||||
@@ -65,7 +92,7 @@ namespace jdi
|
||||
theme.danger = MakeArgb(kRed);
|
||||
theme.warning = MakeArgb(kYellow);
|
||||
return theme;
|
||||
}();
|
||||
}());
|
||||
|
||||
/**
|
||||
* @brief 浅色主题(参考 VS Code 2026 的默认浅色配色)。
|
||||
@@ -73,7 +100,7 @@ namespace jdi
|
||||
* 与 Solarised Light 的区别:底色是**中性白/浅灰**而不是暖米色,
|
||||
* 强调色是 VS Code 的系统蓝 `#0078D4`,描边是中性灰。
|
||||
*/
|
||||
const Theme kLight = []
|
||||
const Theme kLight = NormalizePlotContrast([]
|
||||
{
|
||||
Theme theme;
|
||||
theme.windowBg = MakeArgb(0xFFFFFFu); // editor.background
|
||||
@@ -96,6 +123,7 @@ namespace jdi
|
||||
theme.selection = MakeArgb(0xE8E8E8u);
|
||||
|
||||
// 白底上网格线必须够淡(否则抢波形),但主刻线要能与次级线区分。
|
||||
// ⚠️ 这三个颜色会被 `NormalizePlotContrast` 按白底自动校正到可见水位。
|
||||
theme.gridWeak = MakeArgb(0xEDEDEDu);
|
||||
theme.gridStrong = MakeArgb(0xD6D6D6u);
|
||||
theme.axisLine = MakeArgb(0xCECECEu);
|
||||
@@ -104,12 +132,12 @@ namespace jdi
|
||||
theme.danger = MakeArgb(0xE51400u); // errorForeground
|
||||
theme.warning = MakeArgb(0xBF8803u);
|
||||
return theme;
|
||||
}();
|
||||
}());
|
||||
|
||||
/**
|
||||
* @brief 深色主题(参考 VS Code Dark+)。
|
||||
*/
|
||||
const Theme kDark = []
|
||||
const Theme kDark = NormalizePlotContrast([]
|
||||
{
|
||||
Theme theme;
|
||||
theme.windowBg = MakeArgb(0x1E1E1Eu); // editor.background
|
||||
@@ -131,6 +159,8 @@ namespace jdi
|
||||
theme.pressed = MakeArgb(0x37373Du);
|
||||
theme.selection = MakeArgb(0x04395Eu);
|
||||
|
||||
// ⚠️ 深色底上的原始取值几乎与底色同亮度(差 2~3 个色阶)⇒ 交给
|
||||
// `NormalizePlotContrast` 按 `plotBg` 自动提亮到可见水位。
|
||||
theme.gridWeak = MakeArgb(0x2B2B2Bu);
|
||||
theme.gridStrong = MakeArgb(0x3A3A3Au);
|
||||
theme.axisLine = MakeArgb(0x4A4A4Au);
|
||||
@@ -139,7 +169,7 @@ namespace jdi
|
||||
theme.danger = MakeArgb(0xF44747u);
|
||||
theme.warning = MakeArgb(0xCCA700u);
|
||||
return theme;
|
||||
}();
|
||||
}());
|
||||
|
||||
/**
|
||||
* @brief Solarised Dark(参考 VS Code 的 Solarized Dark)。
|
||||
@@ -147,7 +177,7 @@ namespace jdi
|
||||
* 底色用 base03、面板用 base02,强调色仍是 Solarised 那一套 —— 因此波形配色表
|
||||
* (`SignalPalette`)与 Solarised Light 完全一致。
|
||||
*/
|
||||
const Theme kSolarizedDark = []
|
||||
const Theme kSolarizedDark = NormalizePlotContrast([]
|
||||
{
|
||||
Theme theme;
|
||||
theme.windowBg = MakeArgb(kBase03);
|
||||
@@ -177,12 +207,121 @@ namespace jdi
|
||||
theme.danger = MakeArgb(kRed);
|
||||
theme.warning = MakeArgb(kYellow);
|
||||
return theme;
|
||||
}();
|
||||
}());
|
||||
|
||||
/** @brief 全局「当前主题」指针(由宿主设置,见 `SetCurrentTheme`)。 */
|
||||
const Theme* g_currentTheme = &kSolarizedLight;
|
||||
}
|
||||
|
||||
double SrgbLuminance(std::uint32_t argb)
|
||||
{
|
||||
// sRGB → 线性光:> 0.03928 用 2.4 次幂,否则用 12.92 线性段(WCAG 2.x)。
|
||||
const auto channel = [](std::uint32_t value) -> double
|
||||
{
|
||||
const double c = static_cast<double>(value & 0xFFu) / 255.0;
|
||||
return (c <= 0.03928) ? (c / 12.92) : std::pow((c + 0.055) / 1.055, 2.4);
|
||||
};
|
||||
const double r = channel((argb >> 16) & 0xFFu);
|
||||
const double g = channel((argb >> 8) & 0xFFu);
|
||||
const double b = channel(argb & 0xFFu);
|
||||
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
||||
}
|
||||
|
||||
double ContrastRatio(std::uint32_t firstColor, std::uint32_t secondColor)
|
||||
{
|
||||
const double first = SrgbLuminance(firstColor);
|
||||
const double second = SrgbLuminance(secondColor);
|
||||
const double high = std::max(first, second);
|
||||
const double low = std::min(first, second);
|
||||
return (high + 0.05) / (low + 0.05);
|
||||
}
|
||||
|
||||
std::uint32_t EnsureContrast(std::uint32_t background, std::uint32_t foreground, double minRatio)
|
||||
{
|
||||
if (!(minRatio > 1.0) || ContrastRatio(background, foreground) >= minRatio)
|
||||
{
|
||||
return foreground; // 已达标(或不限制):**逐位返回原色**
|
||||
}
|
||||
// 远离底色:深底就提亮、浅底就加深。二分求解"刚好达标"的混色量,
|
||||
// 使输出随底色**连续**变化(不会在阈值附近两个极端色之间跳)。
|
||||
const bool lighten = SrgbLuminance(background) < 0.5;
|
||||
const std::uint32_t extreme = lighten ? 0xFFFFFFFFu : 0xFF000000u;
|
||||
double low = 0.0;
|
||||
double high = 1.0;
|
||||
for (int iteration = 0; iteration < 18; ++iteration)
|
||||
{
|
||||
const double middle = (low + high) * 0.5;
|
||||
if (ContrastRatio(background, MixColor(foreground, extreme, middle)) < minRatio)
|
||||
{
|
||||
low = middle;
|
||||
}
|
||||
else
|
||||
{
|
||||
high = middle;
|
||||
}
|
||||
}
|
||||
return MixColor(foreground | 0xFF000000u, extreme, high);
|
||||
}
|
||||
|
||||
std::uint32_t MixToLuminance(std::uint32_t color, double targetLuminance)
|
||||
{
|
||||
const std::uint32_t base = color | 0xFF000000u;
|
||||
const double current = SrgbLuminance(base);
|
||||
if (!(targetLuminance > 0.0))
|
||||
{
|
||||
targetLuminance = 0.0;
|
||||
}
|
||||
if (targetLuminance > 1.0)
|
||||
{
|
||||
targetLuminance = 1.0;
|
||||
}
|
||||
if (std::fabs(targetLuminance - current) < 1.0e-4)
|
||||
{
|
||||
return base;
|
||||
}
|
||||
// 亮度沿"混向白 / 混向黑"单调 ⇒ 二分解出混色量;
|
||||
// 目标亮度等于当前亮度时混色量为 0(等价返回原色),因此两侧在该点**连续衔接**。
|
||||
const std::uint32_t extreme = (targetLuminance > current) ? 0xFFFFFFFFu : 0xFF000000u;
|
||||
double low = 0.0;
|
||||
double high = 1.0;
|
||||
for (int iteration = 0; iteration < 20; ++iteration)
|
||||
{
|
||||
const double middle = (low + high) * 0.5;
|
||||
const double luminance = SrgbLuminance(MixColor(base, extreme, middle));
|
||||
if (targetLuminance > current)
|
||||
{
|
||||
if (luminance < targetLuminance)
|
||||
{
|
||||
low = middle;
|
||||
}
|
||||
else
|
||||
{
|
||||
high = middle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (luminance > targetLuminance)
|
||||
{
|
||||
low = middle;
|
||||
}
|
||||
else
|
||||
{
|
||||
high = middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MixColor(base, extreme, high);
|
||||
}
|
||||
|
||||
std::uint32_t ThemeLaneBackground(const Theme& theme)
|
||||
{
|
||||
// 网格底色必须与绘图区底色**可辨**(否则几十条网格看起来是一整片)。
|
||||
// 用统一的对比度阈值 1.03:本就有差异的主题(Solarised Light / Light / Dark)
|
||||
// 逐位返回 `cardBg`;两侧完全同色的主题(Solarised Dark 的 base03)会被轻轻推开。
|
||||
return EnsureContrast(theme.plotBg | 0xFF000000u, theme.cardBg | 0xFF000000u, 1.03);
|
||||
}
|
||||
|
||||
const Theme& ThemeFor(ThemeKind kind)
|
||||
{
|
||||
switch (kind)
|
||||
|
||||
Reference in new issue
Block a user