[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
104
lib/fontWeightAvailability.ts
Normal file
104
lib/fontWeightAvailability.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { extractPrimaryFamily } from './fontAvailability';
|
||||
|
||||
/** Weights actually shipped via @fontsource in index.tsx. */
|
||||
export const BUNDLED_FONT_WEIGHTS: Readonly<Record<string, readonly number[]>> = {
|
||||
'JetBrains Mono': [400, 500, 600],
|
||||
};
|
||||
|
||||
export type FontWeightMeasureContext = {
|
||||
measureText: (font: string, text: string) => TextMetrics;
|
||||
};
|
||||
|
||||
const BOLD_PROBE = 'WMwm0123456789';
|
||||
|
||||
export function pickNearestBundledWeight(
|
||||
available: readonly number[],
|
||||
desired: number,
|
||||
normal: number,
|
||||
): number {
|
||||
if (available.includes(desired)) return desired;
|
||||
const heavier = available.filter((weight) => weight > normal);
|
||||
if (heavier.length === 0) return normal;
|
||||
return heavier.reduce((best, weight) =>
|
||||
Math.abs(weight - desired) < Math.abs(best - desired) ? weight : best,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* True when rendering `boldWeight` produces measurably different glyphs than
|
||||
* `normalWeight` for `family`. Unlike document.fonts.check(), this does not
|
||||
* false-positive on syntactically valid but unavailable families/weights in
|
||||
* Chromium (see fontAvailability.ts).
|
||||
*/
|
||||
export function isBoldWeightDistinctWithContext(
|
||||
family: string,
|
||||
normalWeight: number,
|
||||
boldWeight: number,
|
||||
fontSize: number,
|
||||
ctx: FontWeightMeasureContext,
|
||||
): boolean {
|
||||
if (boldWeight <= normalWeight) return false;
|
||||
|
||||
const quoted = /\s/.test(family) ? `"${family}"` : family;
|
||||
const normalFont = `${normalWeight} ${fontSize}px ${quoted}, monospace`;
|
||||
const boldFont = `${boldWeight} ${fontSize}px ${quoted}, monospace`;
|
||||
|
||||
const normalMetrics = ctx.measureText(normalFont, BOLD_PROBE);
|
||||
const boldMetrics = ctx.measureText(boldFont, BOLD_PROBE);
|
||||
|
||||
if (Math.abs(boldMetrics.width - normalMetrics.width) > 0.01) return true;
|
||||
|
||||
const normalAscent = normalMetrics.actualBoundingBoxAscent ?? 0;
|
||||
const boldAscent = boldMetrics.actualBoundingBoxAscent ?? 0;
|
||||
if (Math.abs(boldAscent - normalAscent) > 0.01) return true;
|
||||
|
||||
const normalDescent = normalMetrics.actualBoundingBoxDescent ?? 0;
|
||||
const boldDescent = boldMetrics.actualBoundingBoxDescent ?? 0;
|
||||
return Math.abs(boldDescent - normalDescent) > 0.01;
|
||||
}
|
||||
|
||||
function buildBrowserMeasureContext(): FontWeightMeasureContext | null {
|
||||
if (typeof document === 'undefined') return null;
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) return null;
|
||||
return {
|
||||
measureText: (font, text) => {
|
||||
ctx.font = font;
|
||||
return ctx.measureText(text);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the boldest weight xterm can safely rasterize for the primary font.
|
||||
* Falls back to `normalWeight` when the requested bold face is unavailable.
|
||||
*/
|
||||
export function resolveFontWeightBold(args: {
|
||||
fontFamilyCss: string;
|
||||
normalWeight: number;
|
||||
desiredBoldWeight: number;
|
||||
fontSize: number;
|
||||
}): number {
|
||||
const { fontFamilyCss, normalWeight, desiredBoldWeight, fontSize } = args;
|
||||
if (desiredBoldWeight <= normalWeight) return normalWeight;
|
||||
|
||||
const primary = extractPrimaryFamily(fontFamilyCss);
|
||||
const bundled = BUNDLED_FONT_WEIGHTS[primary];
|
||||
if (bundled) {
|
||||
return pickNearestBundledWeight(bundled, desiredBoldWeight, normalWeight);
|
||||
}
|
||||
|
||||
const ctx = buildBrowserMeasureContext();
|
||||
if (!ctx) return desiredBoldWeight;
|
||||
|
||||
return isBoldWeightDistinctWithContext(
|
||||
primary,
|
||||
normalWeight,
|
||||
desiredBoldWeight,
|
||||
fontSize,
|
||||
ctx,
|
||||
)
|
||||
? desiredBoldWeight
|
||||
: normalWeight;
|
||||
}
|
||||
Reference in New Issue
Block a user