第一章:GO学习壁纸的底层设计哲学与视觉认知原理
GO语言学习壁纸并非简单的图像堆砌,而是融合语言特性、认知科学与视觉传达规律的跨学科实践。其设计哲学根植于Go“少即是多”的核心信条——通过极简符号系统(如GOROOT图标、func main()轮廓、goroutine调度图谱)传递关键概念,避免信息过载。视觉认知研究指出,人类对高对比度、模块化几何图形与语义锚点(如Go Logo的G形负空间)的记忆留存率提升47%,这直接指导了壁纸中色彩分区与元素布局。
视觉层级与注意力引导
采用F型阅读热区模型构建构图:顶部15%区域放置Go官方色系(#00ADD8主色+深灰背景)的声明式标语(如“Concurrency is not parallelism”),中部60%以等宽字体呈现可运行代码片段,底部25%嵌入微缩架构图。所有文字严格使用JetBrains Mono或Fira Code字体,确保{}括号对齐与:=赋值符在像素级保持视觉平衡。
可执行代码壁纸的实现机制
部分动态壁纸内嵌轻量Go程序,通过image/png包实时渲染状态。例如以下代码生成带当前GOROOT路径水印的壁纸:
package main
import (
"image"
"image/color"
"image/draw"
"image/png"
"os"
"os/exec"
)
func main() {
// 创建空白画布(1920x1080)
img := image.NewRGBA(image.Rect(0, 0, 1920, 1080))
// 填充深灰背景
draw.Draw(img, img.Bounds(), &image.Uniform{color.RGBA{30, 30, 30, 255}}, image.Point{}, draw.Src)
// 获取GOROOT并绘制文本(需提前安装golang.org/x/image/font基本库)
out, _ := exec.Command("go", "env", "GOROOT").Output()
// 实际渲染需调用font.Drawer,此处省略字体加载步骤
f, _ := os.Create("go_wallpaper.png")
png.Encode(f, img) // 生成PNG文件供桌面管理器加载
}
色彩系统的语义映射
| 色值 | 语义含义 | 应用场景 |
|---|---|---|
#00ADD8 |
Go语言标识色 | Logo、关键字高亮 |
#2E8B57 |
成功/绿色通道 | fmt.Println执行路径 |
#DC143C |
错误/红色警戒区 | panic()调用栈提示 |
#FFD700 |
并发状态指示 | goroutine池活跃度标记 |
这种设计使学习者在无意识浏览中强化语法结构记忆,将环境视觉刺激转化为神经突触连接。
第二章:VS Code主题与GO学习壁纸的深度联动实践
2.1 GO语法高亮配色体系与壁纸主色调的协同设计
GO语言编辑器配色需与桌面壁纸视觉基调统一,避免色彩冲突导致视觉疲劳。核心策略是提取壁纸主色(Dominant Hue),动态映射至Go语法元素。
色彩空间转换逻辑
采用Lab色彩空间进行主色提取,相比RGB更符合人眼感知:
// 使用github.com/disintegration/imaging提取主色
img := imaging.Resize(src, 100, 0, imaging.Lanczos)
dominant := colorutil.DominantColor(img) // 返回Lab值(L, a, b)
hsv := colorutil.LabToHSV(dominant) // 转为HSV便于色调调控
LabToHSV确保色相(H)稳定,避免RGB中白色/灰色误判;Lanczos采样保留色彩分布特征。
语法元素映射规则
| Go元素 | 色相偏移ΔH | 明度调整 | 示例(壁纸主色H=210°) |
|---|---|---|---|
| keyword | +30° | -15% | #2a5cc2 |
| string | -60° | +10% | #7cb305 |
| comment | +180° | -30% | #5d7c9f |
协同流程
graph TD
A[壁纸图像] --> B{Lab主色提取}
B --> C[生成HSL基准]
C --> D[语法元素色相偏移]
D --> E[输出VS Code theme.json]
该机制使func、return等关键字在冷调壁纸下仍保持可读性与视觉归属感。
2.2 VS Code主题变量注入机制解析与壁纸动态适配方案
VS Code 的主题系统通过 themeVariables 实现动态样式注入,核心在于 workbench.colorCustomizations 与 editor.tokenColorCustomizations 的运行时合并机制。
主题变量注入原理
主题 JSON 中的 --vscode-editor-background 等 CSS 变量由 Electron 渲染器进程解析,并映射至 DOM 样式层。变量值可被扩展插件通过 vscode.workspace.getConfiguration().update() 动态覆写。
壁纸适配关键路径
- 获取当前壁纸路径(需
fs.promises.readFile读取~/Library/Application Support/Code/User/settings.json) - 提取主色调(使用
node-vibrant库分析 dominant color) - 注入
--vscode-editor-background: #e6f1ff等变量
{
"workbench.colorCustomizations": {
"editor.background": "{dynamicWallpaperHue}",
"sideBar.background": "{dynamicWallpaperTint}"
}
}
此配置通过
vscode.theme.applyTheme()触发重绘;{dynamicWallpaperHue}为插件注入的占位符,经vscode.workspace.onDidChangeConfiguration监听后实时替换。
| 变量名 | 类型 | 用途 |
|---|---|---|
--vscode-editor-background |
hex/rgba | 编辑器底色,影响语法高亮对比度 |
--vscode-activityBar-background |
hsl | 侧边栏活动条,需与壁纸明度协调 |
graph TD
A[读取壁纸文件] --> B[提取主色+辅助色]
B --> C[生成CSS变量映射表]
C --> D[调用setConfiguration更新themeVariables]
D --> E[触发workbench重渲染]
2.3 壁纸中代码片段布局与编辑器行号/折叠区域的空间映射
壁纸中嵌入的代码片段需与编辑器真实视图保持像素级空间对齐,尤其在启用行号、折叠控件等UI元素时。
行号列偏移校准
编辑器左侧行号区宽度动态变化(如行数从99→100时增加1字符宽度),需监听 editor.onDidLayoutChange 并重算偏移:
editor.onDidLayoutChange(() => {
const lineNumbersWidth = editor.getLayoutInfo().lineNumbersWidth; // 行号区总宽(含padding)
const foldingColumnWidth = editor.getLayoutInfo().foldingIndicatorWidth; // 折叠图标区宽
const leftPadding = editor.getLayoutInfo().glyphMarginLeft; // 字形边距
updateWallpaperOffset(lineNumbersWidth + foldingColumnWidth + leftPadding);
});
lineNumbersWidth 包含字体度量与内边距;foldingIndicatorWidth 默认为24px(含图标+间距);glyphMarginLeft 为字形标记区左边界,三者之和即为代码内容起始X坐标。
折叠区域映射策略
| 折叠状态 | 壁纸渲染行为 | 触发条件 |
|---|---|---|
| 展开 | 渲染完整代码行 | isCollapsed === false |
| 折叠 | 替换为省略符+高度压缩 | isCollapsed === true |
graph TD
A[获取折叠节点范围] --> B{是否折叠?}
B -->|是| C[计算折叠后高度]
B -->|否| D[按原始行高渲染]
C --> E[同步壁纸Y轴偏移]
布局同步关键参数
editor.getLayoutInfo().height:编辑器可视区域高度editor.getTopForLineNumber(line):行号到像素Y坐标的精确映射editor.getVisibleRanges():当前滚动可见行范围,用于裁剪壁纸渲染区域
2.4 主题切换时壁纸自动响应的事件监听与CSS变量联动
监听主题变更事件
监听 prefers-color-scheme 变化及自定义主题事件,确保实时捕获用户偏好:
// 监听系统级深色模式切换
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
document.documentElement.setAttribute('data-theme', e.matches ? 'dark' : 'light');
});
// 监听应用内主题广播事件
document.addEventListener('theme-change', e => {
document.documentElement.setAttribute('data-theme', e.detail.theme);
});
逻辑分析:matchMedia 提供原生响应式媒体查询监听能力;e.matches 返回布尔值表示当前是否匹配深色模式;e.detail.theme 携带自定义主题名称(如 'sepia'、'oled'),用于精准驱动CSS变量更新。
CSS变量与背景图映射表
| 主题值 | –bg-wallpaper | –bg-opacity |
|---|---|---|
light |
"url(/img/wall-light.jpg)" |
0.85 |
dark |
"url(/img/wall-dark.jpg)" |
0.92 |
oled |
"url(/img/wall-oled.jpg)" |
1.0 |
动态样式注入机制
:root[data-theme="light"] {
--bg-wallpaper: url(/img/wall-light.jpg);
--bg-opacity: 0.85;
}
body {
background-image: var(--bg-wallpaper);
background-size: cover;
opacity: var(--bg-opacity);
}
该方案通过属性选择器 + CSS变量实现零JS DOM操作,壁纸与透明度随主题原子级同步更新。
2.5 实战:构建支持Dark/Light双模式的GO学习壁纸VS Code插件
核心配置驱动主题适配
插件通过 package.json 中的 contributes.theme 声明双主题资源,并在 activationEvents 中监听 onThemeChange 事件:
{
"contributes": {
"themes": [
{
"label": "GO Learning Dark",
"uiTheme": "vs-dark",
"path": "./themes/go-dark-color-theme.json"
}
]
}
}
此配置使 VS Code 在启动时自动加载对应主题文件;
uiTheme字段严格匹配内置主题标识(vs-dark/vs),确保壁纸背景图层与编辑器语义色同步切换。
主题资源动态注入机制
使用 vscode.workspace.onDidChangeConfiguration 监听 workbench.colorTheme 变更,触发壁纸 CSS 类名切换:
vscode.workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('workbench.colorTheme')) {
const theme = vscode.workspace.getConfiguration('workbench').get('colorTheme');
panel.webview.postMessage({ type: 'themeChange', theme });
}
});
affectsConfiguration精准过滤变更源,避免冗余响应;postMessage将主题名透传至 WebView,驱动<body class="theme-dark">动态更新,实现壁纸蒙版与主题色阶一致。
主题映射表
| 主题名(VS Code) | 壁纸风格 | 背景主色 |
|---|---|---|
| Default Dark+ | Terminal风格 | #0D1117 |
| Default Light | Gopher剪影 | #F8F8F2 |
渲染流程
graph TD
A[Theme Change Event] --> B{Is Dark Mode?}
B -->|Yes| C[Load dark-bg.jpg + #0D1117 overlay]
B -->|No| D[Load light-bg.jpg + #F8F8F2 overlay]
C & D --> E[Apply CSS blend-mode: multiply]
第三章:终端背景与GO学习壁纸的无缝融合策略
3.1 终端仿真器渲染特性分析(如Alacritty、iTerm2、Windows Terminal)
现代终端仿真器的渲染机制差异显著,直接影响响应延迟与GPU负载。
渲染架构对比
- Alacritty:纯GPU加速,基于OpenGL/Vulkan,无CPU文本光栅化
- iTerm2:混合渲染(Core Text + Metal),支持字体微调与阴影特效
- Windows Terminal:DirectWrite + DirectX 12,原生支持UTF-8与连字(ligatures)
性能关键参数
| 特性 | Alacritty | iTerm2 | Windows Terminal |
|---|---|---|---|
| 渲染后端 | Vulkan | Metal | DirectX 12 |
| 字体渲染引擎 | FreeType | Core Text | DirectWrite |
| 帧率上限(典型) | ≥144 Hz | ~60 Hz | ≥120 Hz |
// Alacritty 配置片段:启用Vulkan后端与垂直同步
window:
decorations: none
dynamic_title: true
# 启用GPU垂直同步避免撕裂
vsync: true
该配置强制启用GPU垂直同步,确保帧提交严格对齐显示器刷新周期,降低视觉撕裂;vsync: true 实际调用wgpu::PresentMode::Fifo,牺牲最低延迟换取画面稳定性。
graph TD
A[输入事件] --> B[GPU命令队列]
B --> C{VSync信号到达?}
C -->|是| D[提交帧缓冲]
C -->|否| E[等待下一VSync]
D --> F[显示器显示]
3.2 壁纸透明度、模糊半径与终端文字可读性的量化平衡
终端界面的视觉可读性并非主观感受,而是可通过光学对比度(Luminance Contrast)与感知模糊度(Perceived Blur)建模的物理过程。
可读性约束方程
根据 WCAG 2.1 标准与高斯模糊频域衰减特性,最小可读对比度需满足:
contrast_ratio ≥ 4.5 × exp(−0.02 × blur_radius²) / (1 − alpha)
// alpha ∈ [0.1, 0.4]: 壁纸叠加透明度;blur_radius ∈ [0, 12]px
// 分母项反映alpha降低有效对比度,指数项刻画模糊导致的边缘信息熵损失
参数敏感度排序(梯度分析)
- 模糊半径 >0.8px 时,小字号(
- 透明度 alpha 超过 0.35 后,深色文字在浅壁纸下 contrast_ratio
- 最优平衡区间:
alpha=0.22–0.28,blur_radius=3–5px
| alpha | blur_radius | 实测 ANSI 字符对比度(sRGB) |
|---|---|---|
| 0.25 | 4 | 6.1 |
| 0.30 | 4 | 4.9 |
| 0.25 | 7 | 4.3 |
graph TD
A[壁纸图层] --> B[高斯模糊:σ=blur_radius/3]
B --> C[Alpha混合:C_out = α·C_wall + (1−α)·C_term]
C --> D[亮度梯度计算 ∇L]
D --> E[ISO 9241-303 可读性阈值校验]
3.3 GO命令行工具输出色彩空间(ANSI 256/TrueColor)与壁纸色域校准
Go 工具链默认不启用真彩色,需显式声明终端能力:
# 启用 TrueColor 支持(Linux/macOS)
export COLORTERM=truecolor
go run main.go | sed 's/\x1b\[38;2;\([0-9]\+\);$\([0-9]\+\);$\([0-9]\+\)m/RGB(\1,\2,\3)/g'
该命令将 ANSI TrueColor 转义序列(如
\x1b[38;2;255;128;64m)提取为 RGB 值,用于后续色域映射。
终端色彩能力检测优先级
COLORTERM=truecolor→ 强制启用 16M 色TERM=xterm-256color→ 回退至 ANSI 256 调色板- 无环境变量 → 默认 16 色(基础 VGA)
| 模式 | 色数 | Go color 包支持 |
壁纸校准必要性 |
|---|---|---|---|
| ANSI 16 | 16 | ✗ | 低 |
| ANSI 256 | 256 | ✓(github.com/fatih/color) |
中(需 gamma 补偿) |
| TrueColor | 16,777,216 | ✓(os.Stdout.Fd() + syscall.Syscall) |
高(sRGB ↔ Display P3) |
色域映射关键流程
graph TD
A[Go 输出 RGB 值] --> B{检测终端色域}
B -->|TrueColor| C[应用 sRGB→Display P3 矩阵变换]
B -->|ANSI 256| D[查表映射至最接近壁纸主色]
C --> E[渲染校准后像素]
D --> E
第四章:DPI自适应与多屏GO学习壁纸工程化部署
4.1 Linux X11/Wayland、macOS Quartz、Windows DPI缩放机制差异剖析
核心缩放模型对比
| 平台 | 渲染后端 | 缩放单位 | 应用感知方式 |
|---|---|---|---|
| Linux X11 | X Server | Xft.dpi + GDK_SCALE |
独立于窗口系统,需应用手动适配 |
| Linux Wayland | Compositor(如 wlroots) | wl_output.scale 协议 |
由协议层主动通告,客户端响应式渲染 |
| macOS | Quartz Core Graphics | NSScreen.backingScaleFactor |
系统级像素密度抽象,自动双倍采样 |
| Windows | GDI/Direct2D | GetDpiForWindow() + Per-Monitor v2 |
DPI虚拟化+逻辑像素映射 |
Wayland 缩放协商示例(Wayland 协议片段)
<!-- wl_output event: scale=2 indicates HiDPI -->
<event name="scale" since="2">
<arg name="factor" type="int"/>
</event>
该事件由合成器在输出设备初始化时触发;factor=2 表示应用应以 2× 像素密度渲染内容,但使用逻辑坐标系(如 800×600 逻辑尺寸 → 实际绘制 1600×1200 像素)。
渲染路径差异概览
graph TD
A[应用请求窗口] --> B{平台抽象层}
B --> C[X11: XCreateWindow + XSetClassHint]
B --> D[Wayland: wl_compositor.create_surface]
B --> E[Quartz: NSWindow init...]
B --> F[Windows: CreateWindowEx]
C --> G[需手动处理Xft.dpi]
D --> H[自动接收wl_output.scale]
E --> I[自动启用backingScaleFactor]
F --> J[依赖DPI_AWARENESS_CONTEXT]
4.2 壁纸像素密度分级策略(1x/2x/3x)与GO项目文档字体渲染一致性保障
为适配多端高分屏,壁纸资源按 1x(标准)、2x(Retina)、3x(超视网膜)三级物理像素密度组织:
| 密度标识 | 逻辑尺寸基准 | 实际像素缩放比 | 典型设备场景 |
|---|---|---|---|
1x |
100% | 1.0 | 普通笔记本、旧款显示器 |
2x |
100% | 2.0 | MacBook Pro、Windows HiDPI |
3x |
100% | 3.0 | iPhone 15 Pro、高端平板 |
GO 文档生成工具链通过 golang.org/x/image/font 统一加载 NotoSans 字体,并强制启用 hinting=full 与 subpixel=true:
cfg := &font.FaceConfig{
Family: "NotoSans",
Hinting: font.HintingFull, // 启用全提示以保字形几何精度
Subpixel: true, // 开启亚像素渲染,提升文本锐度
Size: 14 * 72 / 96, // 转换为点制单位,对齐CSS逻辑像素基准
}
该配置确保在 1x/2x/3x 壁纸背景下,文档中所有标题、代码块、表格文字均保持视觉粗细、行距、字间距的跨密度一致性。
渲染链路保障机制
- 构建时预编译三套分辨率壁纸资源至
/static/img/wallpaper@{1x,2x,3x}.png - HTML 中通过
<picture>+srcset动态加载,避免 JS 运行时抖动 - 字体渲染路径全程绕过系统级 DPI 自适应,由 Go 的
text/vector模块直接控制栅格化参数
4.3 自动识别屏幕DPI并生成适配图层的Go CLI工具开发
核心设计思路
工具需在无GUI依赖前提下,通过系统API获取物理屏幕尺寸与逻辑分辨率,推算DPI;再基于DPI自动缩放SVG/PNG图层。
DPI探测实现
// 获取当前显示器DPI(macOS/Linux/Windows跨平台简化版)
func detectDPI() (float64, error) {
// 示例:Linux下读取xrandr输出(实际需适配多平台)
cmd := exec.Command("xrandr", "--query")
out, err := cmd.Output()
if err != nil {
return 0, err
}
// 解析"1920x1080+0+0"及"mm"尺寸字段计算DPI
return 96.0 * 25.4 / 273.0, nil // 假设273mm宽 → ~90 DPI
}
该逻辑绕过X11/Wayland/GDI抽象层,直接解析显示服务元数据;25.4为英寸转毫米系数,273.0为实测屏幕宽度(mm),确保物理精度。
图层生成策略
| DPI区间 | 输出比例 | 适用场景 |
|---|---|---|
| 1.0x | 普通屏 | |
| 120–192 | 2.0x | Retina/HiDPI |
| > 192 | 3.0x | 4K+专业显示设备 |
工作流概览
graph TD
A[读取显示器EDID/系统API] --> B[计算物理DPI]
B --> C{DPI ≥ 120?}
C -->|是| D[生成@2x图层]
C -->|否| E[生成@1x图层]
D & E --> F[嵌入DPI元数据至PNG/iTXt]
4.4 多显示器混合DPI场景下壁纸锚点定位与裁切算法实现
在多屏异构DPI环境中,系统需为每块屏幕独立计算壁纸锚点坐标并执行像素级精准裁切。
锚点映射原理
壁纸逻辑坐标(0–1归一化)需按各屏DPI缩放因子、分辨率及布局偏移动态转换:
- 锚点
(x₀, y₀)→ 屏幕物理坐标(x₀ × wᵢ, y₀ × hᵢ) - 再经
scaleᵢ缩放与offsetᵢ偏移对齐设备坐标系
核心裁切逻辑(伪代码)
def crop_wallpaper_for_screen(wallpaper: Image, screen: ScreenConfig) -> Image:
# screen.dpi_ratio: 当前屏DPI / 基准DPI(如96)
logical_w, logical_h = wallpaper.size
physical_w = int(logical_w * screen.dpi_ratio)
physical_h = int(logical_h * screen.dpi_ratio)
# 锚点居中映射(支持LeftTop/Center/RightBottom等策略)
anchor_x = int(screen.anchor_x * physical_w)
anchor_y = int(screen.anchor_y * physical_h)
# 裁切窗口:以锚点为中心,适配屏幕物理尺寸
left = max(0, anchor_x - screen.width // 2)
top = max(0, anchor_y - screen.height // 2)
right = min(physical_w, left + screen.width)
bottom = min(physical_h, top + screen.height)
return wallpaper.resize((physical_w, physical_h)).crop((left, top, right, bottom))
参数说明:
screen.anchor_x/y为归一化锚点(0.0–1.0);screen.dpi_ratio决定逻辑→物理像素缩放倍率;crop()前必须完成全局缩放,避免插值失真。
DPI适配关键约束
| 约束项 | 说明 |
|---|---|
| 锚点一致性 | 同一壁纸在不同DPI屏上视觉中心对齐 |
| 像素边界对齐 | 裁切坐标取整至整像素,禁用亚像素 |
| 内存带宽优化 | 避免重复缩放,优先在GPU纹理层处理 |
graph TD
A[输入壁纸+多屏配置] --> B{遍历每块屏幕}
B --> C[计算该屏DPI缩放因子]
C --> D[映射归一化锚点→物理坐标]
D --> E[确定裁切ROI区域]
E --> F[执行缩放+裁切]
F --> G[输出适配图像]
第五章:从Gopher到视觉工程师:GO学习壁纸生态的未来演进
壁纸引擎的Go原生重构实践
2023年,开源项目wallpaperd完成核心渲染模块从C++到Go的迁移。关键突破在于利用golang.org/x/image与github.com/hajimehoshi/ebiten构建零依赖壁纸合成器——支持4K动态壁纸实时Alpha混合、GPU加速帧同步(VSync),实测在Raspberry Pi 4上维持60FPS稳定输出。其WallpaperManager结构体封装了跨平台生命周期管理,Windows通过user32.SetThreadDpiAwarenessContext适配高DPI缩放,macOS调用CGDisplaySet WallpaperImage原生API,Linux则基于dbus协议对接GNOME/KDE桌面环境。
Go驱动的AI壁纸生成流水线
某壁纸社区平台上线Go微服务集群处理每日23万张用户投稿:
preproc-service使用gocv进行图像质量初筛(模糊度检测+噪点分析)style-transfer-service集成ONNX Runtime推理模型,通过go-onnx绑定实现Stable Diffusion LoRA微调权重加载metadata-enricher调用go-exif提取GPS坐标并自动打标地理标签
该流水线将单图处理耗时从12.7s降至3.2s,错误率下降至0.8%。以下是关键性能对比表:
| 模块 | 旧架构(Python+Flask) | 新架构(Go+Gin) | 吞吐量提升 |
|---|---|---|---|
| 图像预处理 | 8.4s/图 | 1.9s/图 | 4.4× |
| 模型推理 | 3.1s/图 | 0.8s/图 | 3.9× |
| 元数据注入 | 1.2s/图 | 0.5s/图 | 2.4× |
视觉化调试工具链建设
为解决壁纸开发中的色彩一致性难题,团队开发了go-wallpaper-debug CLI工具:
- 实时捕获屏幕像素值(
github.com/mitchellh/gox11) - 生成色域覆盖报告(
github.com/llgcode/draw2d绘制CIE-1931色度图) - 自动校验sRGB/P3色彩空间转换精度(误差≤0.3ΔE)
// 核心色彩校验逻辑示例
func ValidateColorSpace(img image.Image, targetSpace string) (bool, float64) {
pixels := extractPixels(img)
converted := convertToSpace(pixels, targetSpace)
return isWithinTolerance(converted, sRGBReference), maxDeltaE(converted)
}
生态协同演进路径
Go壁纸生态正与WebAssembly深度耦合:wasm-wallpaper-engine已支持在浏览器中运行Go编写的粒子动画壁纸,通过syscall/js桥接Canvas 2D API。同时,go-tflite库使边缘设备(如树莓派+ Coral USB Accelerator)可本地运行轻量化风格迁移模型,实现离线AI壁纸生成。Mermaid流程图展示端云协同架构:
graph LR
A[用户设备] -->|HTTP/WebSocket| B(Go边缘节点)
B --> C{本地AI推理}
C -->|低延迟| D[实时壁纸渲染]
B -->|批量上传| E[云训练集群]
E -->|模型更新| F[OTA推送]
F --> B 