restty 0.1.19 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/app/font-sources.d.ts +1 -1
- package/dist/app/types.d.ts +6 -0
- package/dist/{chunk-53vdvhe3.js → chunk-ef12eja6.js} +274 -35
- package/dist/internal.js +1 -1
- package/dist/restty.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,7 +101,7 @@ restty.copySelectionToClipboard();
|
|
|
101
101
|
|
|
102
102
|
### Provide custom fonts
|
|
103
103
|
|
|
104
|
-
By default, restty uses a
|
|
104
|
+
By default, restty uses a local-first font preset with CDN fallback. To fully control fonts, disable the preset and pass `fontSources`.
|
|
105
105
|
|
|
106
106
|
```ts
|
|
107
107
|
const restty = new Restty({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ResttyFontPreset, ResttyFontSource } from "./types";
|
|
2
|
-
/**
|
|
2
|
+
/** Local-first default font fallback chain with CDN fallback for JetBrains Mono, Nerd symbols, emoji, and CJK support. */
|
|
3
3
|
export declare const DEFAULT_FONT_SOURCES: ResttyFontSource[];
|
|
4
4
|
/** Validates user-provided font sources or returns defaults based on preset (none returns empty array, otherwise default CDN fonts). */
|
|
5
5
|
export declare function normalizeFontSources(sources: ResttyFontSource[] | undefined, preset: ResttyFontPreset | undefined): ResttyFontSource[];
|
package/dist/app/types.d.ts
CHANGED
|
@@ -154,6 +154,12 @@ export type ResttyAppOptions = {
|
|
|
154
154
|
renderer?: "auto" | "webgpu" | "webgl2";
|
|
155
155
|
/** Font size in CSS pixels. */
|
|
156
156
|
fontSize?: number;
|
|
157
|
+
/**
|
|
158
|
+
* Font sizing mode used by text-shaper scale resolution.
|
|
159
|
+
* - em: interpret fontSize as EM size
|
|
160
|
+
* - height: interpret fontSize as full font height (ascender-descender-lineGap)
|
|
161
|
+
*/
|
|
162
|
+
fontSizeMode?: "em" | "height";
|
|
157
163
|
/**
|
|
158
164
|
* Alpha blending strategy.
|
|
159
165
|
* - native: GPU-native premultiplied alpha
|
|
@@ -26598,7 +26598,7 @@ function buildFontAtlasIfNeeded(params) {
|
|
|
26598
26598
|
if (union.size === 0) {
|
|
26599
26599
|
return { rebuilt: false, atlas: null, rgba: null, preferNearest: false };
|
|
26600
26600
|
}
|
|
26601
|
-
const useHinting =
|
|
26601
|
+
const useHinting = false;
|
|
26602
26602
|
const atlasPadding = isSymbol ? Math.max(constants.atlasPadding, constants.symbolAtlasPadding) : constants.atlasPadding;
|
|
26603
26603
|
const atlasMaxSize = isSymbol ? constants.symbolAtlasMaxSize : constants.defaultAtlasMaxSize;
|
|
26604
26604
|
const glyphPixelMode = resolveGlyphPixelMode(entry);
|
|
@@ -26690,9 +26690,79 @@ function buildFontAtlasIfNeeded(params) {
|
|
|
26690
26690
|
|
|
26691
26691
|
// src/app/font-sources.ts
|
|
26692
26692
|
var DEFAULT_FONT_SOURCES = [
|
|
26693
|
+
{
|
|
26694
|
+
type: "local",
|
|
26695
|
+
matchers: [
|
|
26696
|
+
"jetbrainsmono nerd font",
|
|
26697
|
+
"jetbrains mono nerd font",
|
|
26698
|
+
"jetbrains mono nl nerd font mono",
|
|
26699
|
+
"jetbrains mono",
|
|
26700
|
+
"jetbrainsmono"
|
|
26701
|
+
],
|
|
26702
|
+
label: "JetBrains Mono Nerd Font Regular (Local)"
|
|
26703
|
+
},
|
|
26704
|
+
{
|
|
26705
|
+
type: "local",
|
|
26706
|
+
matchers: [
|
|
26707
|
+
"jetbrainsmono nerd font bold",
|
|
26708
|
+
"jetbrains mono nerd font bold",
|
|
26709
|
+
"jetbrains mono nl nerd font mono bold",
|
|
26710
|
+
"jetbrains mono bold",
|
|
26711
|
+
"jetbrainsmono bold"
|
|
26712
|
+
],
|
|
26713
|
+
label: "JetBrains Mono Nerd Font Bold (Local)"
|
|
26714
|
+
},
|
|
26715
|
+
{
|
|
26716
|
+
type: "local",
|
|
26717
|
+
matchers: [
|
|
26718
|
+
"jetbrainsmono nerd font italic",
|
|
26719
|
+
"jetbrains mono nerd font italic",
|
|
26720
|
+
"jetbrains mono nl nerd font mono italic",
|
|
26721
|
+
"jetbrains mono italic",
|
|
26722
|
+
"jetbrainsmono italic"
|
|
26723
|
+
],
|
|
26724
|
+
label: "JetBrains Mono Nerd Font Italic (Local)"
|
|
26725
|
+
},
|
|
26726
|
+
{
|
|
26727
|
+
type: "local",
|
|
26728
|
+
matchers: [
|
|
26729
|
+
"jetbrainsmono nerd font bold italic",
|
|
26730
|
+
"jetbrains mono nerd font bold italic",
|
|
26731
|
+
"jetbrains mono nl nerd font mono bold italic",
|
|
26732
|
+
"jetbrains mono bold italic",
|
|
26733
|
+
"jetbrainsmono bold italic"
|
|
26734
|
+
],
|
|
26735
|
+
label: "JetBrains Mono Nerd Font Bold Italic (Local)"
|
|
26736
|
+
},
|
|
26693
26737
|
{
|
|
26694
26738
|
type: "url",
|
|
26695
|
-
url: "https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.4.0/patched-fonts/JetBrainsMono/NoLigatures/Regular/JetBrainsMonoNLNerdFontMono-Regular.ttf"
|
|
26739
|
+
url: "https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.4.0/patched-fonts/JetBrainsMono/NoLigatures/Regular/JetBrainsMonoNLNerdFontMono-Regular.ttf",
|
|
26740
|
+
label: "JetBrains Mono Nerd Font Regular"
|
|
26741
|
+
},
|
|
26742
|
+
{
|
|
26743
|
+
type: "url",
|
|
26744
|
+
url: "https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.4.0/patched-fonts/JetBrainsMono/NoLigatures/Bold/JetBrainsMonoNLNerdFontMono-Bold.ttf",
|
|
26745
|
+
label: "JetBrains Mono Nerd Font Bold"
|
|
26746
|
+
},
|
|
26747
|
+
{
|
|
26748
|
+
type: "url",
|
|
26749
|
+
url: "https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.4.0/patched-fonts/JetBrainsMono/NoLigatures/Italic/JetBrainsMonoNLNerdFontMono-Italic.ttf",
|
|
26750
|
+
label: "JetBrains Mono Nerd Font Italic"
|
|
26751
|
+
},
|
|
26752
|
+
{
|
|
26753
|
+
type: "url",
|
|
26754
|
+
url: "https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.4.0/patched-fonts/JetBrainsMono/NoLigatures/BoldItalic/JetBrainsMonoNLNerdFontMono-BoldItalic.ttf",
|
|
26755
|
+
label: "JetBrains Mono Nerd Font Bold Italic"
|
|
26756
|
+
},
|
|
26757
|
+
{
|
|
26758
|
+
type: "local",
|
|
26759
|
+
matchers: [
|
|
26760
|
+
"symbols nerd font mono",
|
|
26761
|
+
"symbols nerd font",
|
|
26762
|
+
"nerd fonts symbols",
|
|
26763
|
+
"nerdfontssymbolsonly"
|
|
26764
|
+
],
|
|
26765
|
+
label: "Symbols Nerd Font (Local)"
|
|
26696
26766
|
},
|
|
26697
26767
|
{
|
|
26698
26768
|
type: "url",
|
|
@@ -50195,6 +50265,12 @@ var DEFAULT_SYMBOL_CONSTRAINT = {
|
|
|
50195
50265
|
align_vertical: "center",
|
|
50196
50266
|
max_constraint_width: 1
|
|
50197
50267
|
};
|
|
50268
|
+
var DEFAULT_APPLE_SYMBOLS_CONSTRAINT = {
|
|
50269
|
+
size: "cover",
|
|
50270
|
+
align_horizontal: "center",
|
|
50271
|
+
align_vertical: "center",
|
|
50272
|
+
max_constraint_width: 1
|
|
50273
|
+
};
|
|
50198
50274
|
var DEFAULT_EMOJI_CONSTRAINT = {
|
|
50199
50275
|
size: "cover",
|
|
50200
50276
|
align_horizontal: "center",
|
|
@@ -50305,6 +50381,7 @@ function createResttyApp(options) {
|
|
|
50305
50381
|
const OVERLAY_SCROLLBAR_MARGIN_CSS_PX = 4;
|
|
50306
50382
|
const OVERLAY_SCROLLBAR_INSET_Y_CSS_PX = 2;
|
|
50307
50383
|
const OVERLAY_SCROLLBAR_MIN_THUMB_CSS_PX = 28;
|
|
50384
|
+
const OVERLAY_SCROLLBAR_CAP_SUPERSAMPLE = 8;
|
|
50308
50385
|
let paused = false;
|
|
50309
50386
|
let backend = "none";
|
|
50310
50387
|
let preferredRenderer = options.renderer ?? "auto";
|
|
@@ -50627,24 +50704,63 @@ function createResttyApp(options) {
|
|
|
50627
50704
|
const y02 = Math.round(y);
|
|
50628
50705
|
const width = Math.max(1, Math.round(w));
|
|
50629
50706
|
const height = Math.max(1, Math.round(h));
|
|
50630
|
-
const radius = Math.min(
|
|
50707
|
+
const radius = Math.min(width * 0.5, height * 0.5);
|
|
50631
50708
|
if (radius <= 0) {
|
|
50632
50709
|
pushRectBox(out, x02, y02, width, height, color);
|
|
50633
50710
|
return;
|
|
50634
50711
|
}
|
|
50635
|
-
const
|
|
50712
|
+
const capRows = Math.min(height, Math.max(1, Math.ceil(radius)));
|
|
50713
|
+
const middleStart = capRows;
|
|
50714
|
+
const middleEnd = Math.max(middleStart, height - capRows);
|
|
50715
|
+
const middleH = middleEnd - middleStart;
|
|
50636
50716
|
if (middleH > 0) {
|
|
50637
|
-
pushRectBox(out, x02, y02 +
|
|
50717
|
+
pushRectBox(out, x02, y02 + middleStart, width, middleH, color);
|
|
50638
50718
|
}
|
|
50639
50719
|
const radiusSq = radius * radius;
|
|
50640
|
-
|
|
50641
|
-
|
|
50642
|
-
|
|
50643
|
-
|
|
50644
|
-
|
|
50645
|
-
|
|
50646
|
-
|
|
50647
|
-
|
|
50720
|
+
const centerX = width * 0.5;
|
|
50721
|
+
const topCenterY = radius;
|
|
50722
|
+
const bottomCenterY = height - radius;
|
|
50723
|
+
const samplesPerAxis = Math.max(1, OVERLAY_SCROLLBAR_CAP_SUPERSAMPLE | 0);
|
|
50724
|
+
const totalSamples = samplesPerAxis * samplesPerAxis;
|
|
50725
|
+
const invSamples = 1 / totalSamples;
|
|
50726
|
+
const alphaBase = color[3];
|
|
50727
|
+
const alphaEpsilon = 1 / 255;
|
|
50728
|
+
const sampleCapPixelCoverage = (localX, localY, centerY) => {
|
|
50729
|
+
let hits = 0;
|
|
50730
|
+
for (let sy = 0;sy < samplesPerAxis; sy += 1) {
|
|
50731
|
+
const sampleY = localY + (sy + 0.5) / samplesPerAxis;
|
|
50732
|
+
for (let sx = 0;sx < samplesPerAxis; sx += 1) {
|
|
50733
|
+
const sampleX = localX + (sx + 0.5) / samplesPerAxis;
|
|
50734
|
+
const dx = sampleX - centerX;
|
|
50735
|
+
const dy = sampleY - centerY;
|
|
50736
|
+
if (dx * dx + dy * dy <= radiusSq)
|
|
50737
|
+
hits += 1;
|
|
50738
|
+
}
|
|
50739
|
+
}
|
|
50740
|
+
return hits * invSamples;
|
|
50741
|
+
};
|
|
50742
|
+
for (let row = 0;row < capRows; row += 1) {
|
|
50743
|
+
const topY = y02 + row;
|
|
50744
|
+
const bottomY = y02 + height - 1 - row;
|
|
50745
|
+
for (let col = 0;col < width; col += 1) {
|
|
50746
|
+
const coverageTop = sampleCapPixelCoverage(col, row, topCenterY);
|
|
50747
|
+
if (coverageTop > 0) {
|
|
50748
|
+
const alpha = alphaBase * coverageTop;
|
|
50749
|
+
if (alpha > alphaEpsilon) {
|
|
50750
|
+
out.push(x02 + col, topY, 1, 1, color[0], color[1], color[2], alpha);
|
|
50751
|
+
}
|
|
50752
|
+
}
|
|
50753
|
+
if (bottomY !== topY) {
|
|
50754
|
+
const localBottomY = height - 1 - row;
|
|
50755
|
+
const coverageBottom = sampleCapPixelCoverage(col, localBottomY, bottomCenterY);
|
|
50756
|
+
if (coverageBottom > 0) {
|
|
50757
|
+
const alpha = alphaBase * coverageBottom;
|
|
50758
|
+
if (alpha > alphaEpsilon) {
|
|
50759
|
+
out.push(x02 + col, bottomY, 1, 1, color[0], color[1], color[2], alpha);
|
|
50760
|
+
}
|
|
50761
|
+
}
|
|
50762
|
+
}
|
|
50763
|
+
}
|
|
50648
50764
|
}
|
|
50649
50765
|
}
|
|
50650
50766
|
function appendOverlayScrollbar(overlayData, total, offset, len) {
|
|
@@ -51833,7 +51949,7 @@ function createResttyApp(options) {
|
|
|
51833
51949
|
font: null,
|
|
51834
51950
|
fonts: [],
|
|
51835
51951
|
fontSizePx: 0,
|
|
51836
|
-
sizeMode: "height",
|
|
51952
|
+
sizeMode: options.fontSizeMode === "em" ? "em" : "height",
|
|
51837
51953
|
fontPickCache: new Map
|
|
51838
51954
|
};
|
|
51839
51955
|
const fontConfig = {
|
|
@@ -53312,6 +53428,33 @@ function createResttyApp(options) {
|
|
|
53312
53428
|
const normalizedMatchers = matchers.map((matcher) => matcher.toLowerCase()).filter(Boolean);
|
|
53313
53429
|
if (!normalizedMatchers.length)
|
|
53314
53430
|
return null;
|
|
53431
|
+
const detectStyleHint = (value) => {
|
|
53432
|
+
const text = value.toLowerCase();
|
|
53433
|
+
let weight = 400;
|
|
53434
|
+
if (/\b(thin|hairline)\b/.test(text))
|
|
53435
|
+
weight = 100;
|
|
53436
|
+
else if (/\b(extra[- ]?light|ultra[- ]?light)\b/.test(text))
|
|
53437
|
+
weight = 200;
|
|
53438
|
+
else if (/\blight\b/.test(text))
|
|
53439
|
+
weight = 300;
|
|
53440
|
+
else if (/\bmedium\b/.test(text))
|
|
53441
|
+
weight = 500;
|
|
53442
|
+
else if (/\b(semi[- ]?bold|demi[- ]?bold)\b/.test(text))
|
|
53443
|
+
weight = 600;
|
|
53444
|
+
else if (/\bbold\b/.test(text))
|
|
53445
|
+
weight = 700;
|
|
53446
|
+
else if (/\b(extra[- ]?bold|ultra[- ]?bold)\b/.test(text))
|
|
53447
|
+
weight = 800;
|
|
53448
|
+
else if (/\b(black|heavy)\b/.test(text))
|
|
53449
|
+
weight = 900;
|
|
53450
|
+
return {
|
|
53451
|
+
bold: /\b(bold|semi[- ]?bold|demi[- ]?bold|extra[- ]?bold|black|heavy)\b/.test(text),
|
|
53452
|
+
italic: /\b(italic|oblique)\b/.test(text),
|
|
53453
|
+
regular: /\b(regular|book|roman|normal)\b/.test(text),
|
|
53454
|
+
weight
|
|
53455
|
+
};
|
|
53456
|
+
};
|
|
53457
|
+
const sourceHint = detectStyleHint(`${label} ${normalizedMatchers.join(" ")}`);
|
|
53315
53458
|
const queryPermission = nav.permissions?.query;
|
|
53316
53459
|
if (queryPermission) {
|
|
53317
53460
|
try {
|
|
@@ -53323,13 +53466,49 @@ function createResttyApp(options) {
|
|
|
53323
53466
|
}
|
|
53324
53467
|
try {
|
|
53325
53468
|
const fonts = await queryLocalFonts();
|
|
53326
|
-
const
|
|
53469
|
+
const matches = fonts.filter((font) => {
|
|
53327
53470
|
const name = `${font.family ?? ""} ${font.fullName ?? ""} ${font.postscriptName ?? ""}`.toLowerCase();
|
|
53328
53471
|
return normalizedMatchers.some((matcher) => name.includes(matcher));
|
|
53329
53472
|
});
|
|
53330
|
-
if (
|
|
53473
|
+
if (matches.length) {
|
|
53474
|
+
const scoreMatch = (font) => {
|
|
53475
|
+
const name = `${font.family ?? ""} ${font.fullName ?? ""} ${font.postscriptName ?? ""}`.toLowerCase();
|
|
53476
|
+
const hint = detectStyleHint(name);
|
|
53477
|
+
let score = 0;
|
|
53478
|
+
for (let i3 = 0;i3 < normalizedMatchers.length; i3 += 1) {
|
|
53479
|
+
if (name.includes(normalizedMatchers[i3]))
|
|
53480
|
+
score += 8;
|
|
53481
|
+
}
|
|
53482
|
+
if (sourceHint.bold || sourceHint.italic) {
|
|
53483
|
+
score += sourceHint.bold === hint.bold ? 40 : -40;
|
|
53484
|
+
score += sourceHint.italic === hint.italic ? 40 : -40;
|
|
53485
|
+
} else {
|
|
53486
|
+
score += !hint.bold && !hint.italic ? 60 : -30;
|
|
53487
|
+
}
|
|
53488
|
+
const targetWeight = sourceHint.bold ? 700 : 400;
|
|
53489
|
+
score -= Math.abs((hint.weight ?? 400) - targetWeight) * 0.25;
|
|
53490
|
+
if (!sourceHint.bold && hint.weight === 400)
|
|
53491
|
+
score += 12;
|
|
53492
|
+
if (!sourceHint.bold && hint.weight < 350)
|
|
53493
|
+
score -= 12;
|
|
53494
|
+
if (!sourceHint.bold && hint.weight > 650)
|
|
53495
|
+
score -= 8;
|
|
53496
|
+
if (sourceHint.regular && !hint.bold && !hint.italic)
|
|
53497
|
+
score += 20;
|
|
53498
|
+
return score;
|
|
53499
|
+
};
|
|
53500
|
+
let match = matches[0];
|
|
53501
|
+
let bestScore = Number.NEGATIVE_INFINITY;
|
|
53502
|
+
for (let i3 = 0;i3 < matches.length; i3 += 1) {
|
|
53503
|
+
const candidate = matches[i3];
|
|
53504
|
+
const candidateScore = scoreMatch(candidate);
|
|
53505
|
+
if (candidateScore > bestScore) {
|
|
53506
|
+
bestScore = candidateScore;
|
|
53507
|
+
match = candidate;
|
|
53508
|
+
}
|
|
53509
|
+
}
|
|
53331
53510
|
const matchedName = `${match.family ?? ""} ${match.fullName ?? ""} ${match.postscriptName ?? ""}`.trim();
|
|
53332
|
-
console.log(`[font] local matched (${label}): ${matchedName || "unnamed"}`);
|
|
53511
|
+
console.log(`[font] local matched (${label}): ${matchedName || "unnamed"} score=${bestScore}`);
|
|
53333
53512
|
const blob = await match.blob();
|
|
53334
53513
|
return blob.arrayBuffer();
|
|
53335
53514
|
}
|
|
@@ -53550,10 +53729,10 @@ function createResttyApp(options) {
|
|
|
53550
53729
|
}
|
|
53551
53730
|
return "auto";
|
|
53552
53731
|
}
|
|
53553
|
-
function pickFontIndexForText2(text, expectedSpan = 1) {
|
|
53732
|
+
function pickFontIndexForText2(text, expectedSpan = 1, stylePreference = "regular") {
|
|
53554
53733
|
if (!fontState.fonts.length)
|
|
53555
53734
|
return 0;
|
|
53556
|
-
const cacheKey = `${expectedSpan}:${text}`;
|
|
53735
|
+
const cacheKey = `${expectedSpan}:${stylePreference}:${text}`;
|
|
53557
53736
|
const cached = fontState.fontPickCache.get(cacheKey);
|
|
53558
53737
|
if (cached !== undefined)
|
|
53559
53738
|
return cached;
|
|
@@ -53561,6 +53740,17 @@ function createResttyApp(options) {
|
|
|
53561
53740
|
const firstCp = text.codePointAt(0) ?? 0;
|
|
53562
53741
|
const nerdSymbol = isNerdSymbolCodepoint(firstCp);
|
|
53563
53742
|
const presentation = resolvePresentationPreference2(text, chars);
|
|
53743
|
+
const styleHintsEnabled = stylePreference !== "regular" && presentation !== "emoji" && !nerdSymbol;
|
|
53744
|
+
const hasBoldHint = (entry) => /\bbold\b/i.test(entry.label ?? "");
|
|
53745
|
+
const hasItalicHint = (entry) => /\b(italic|oblique)\b/i.test(entry.label ?? "");
|
|
53746
|
+
const stylePredicates = stylePreference === "bold_italic" ? [
|
|
53747
|
+
(entry) => hasBoldHint(entry) && hasItalicHint(entry),
|
|
53748
|
+
(entry) => hasBoldHint(entry),
|
|
53749
|
+
(entry) => hasItalicHint(entry)
|
|
53750
|
+
] : stylePreference === "bold" ? [(entry) => hasBoldHint(entry) && !hasItalicHint(entry), (entry) => hasBoldHint(entry)] : stylePreference === "italic" ? [
|
|
53751
|
+
(entry) => hasItalicHint(entry) && !hasBoldHint(entry),
|
|
53752
|
+
(entry) => hasItalicHint(entry)
|
|
53753
|
+
] : [];
|
|
53564
53754
|
const pickFirstMatch = (predicate) => {
|
|
53565
53755
|
for (let i3 = 0;i3 < fontState.fonts.length; i3 += 1) {
|
|
53566
53756
|
const entry = fontState.fonts[i3];
|
|
@@ -53580,6 +53770,21 @@ function createResttyApp(options) {
|
|
|
53580
53770
|
}
|
|
53581
53771
|
return -1;
|
|
53582
53772
|
};
|
|
53773
|
+
const pickWithStyle = (predicate) => {
|
|
53774
|
+
if (styleHintsEnabled) {
|
|
53775
|
+
for (let i3 = 0;i3 < stylePredicates.length; i3 += 1) {
|
|
53776
|
+
const stylePredicate = stylePredicates[i3];
|
|
53777
|
+
const styledIndex = pickFirstMatch((entry) => {
|
|
53778
|
+
if (!stylePredicate(entry))
|
|
53779
|
+
return false;
|
|
53780
|
+
return predicate ? !!predicate(entry) : true;
|
|
53781
|
+
});
|
|
53782
|
+
if (styledIndex >= 0)
|
|
53783
|
+
return styledIndex;
|
|
53784
|
+
}
|
|
53785
|
+
}
|
|
53786
|
+
return pickFirstMatch(predicate);
|
|
53787
|
+
};
|
|
53583
53788
|
const tryIndex = (index) => {
|
|
53584
53789
|
if (index < 0)
|
|
53585
53790
|
return null;
|
|
@@ -53587,7 +53792,7 @@ function createResttyApp(options) {
|
|
|
53587
53792
|
return index;
|
|
53588
53793
|
};
|
|
53589
53794
|
if (nerdSymbol) {
|
|
53590
|
-
const symbolIndex =
|
|
53795
|
+
const symbolIndex = pickWithStyle((entry) => isNerdSymbolFont(entry) || isSymbolFont(entry));
|
|
53591
53796
|
const result = tryIndex(symbolIndex);
|
|
53592
53797
|
if (result !== null)
|
|
53593
53798
|
return result;
|
|
@@ -53603,7 +53808,7 @@ function createResttyApp(options) {
|
|
|
53603
53808
|
if (result !== null)
|
|
53604
53809
|
return result;
|
|
53605
53810
|
}
|
|
53606
|
-
const firstIndex =
|
|
53811
|
+
const firstIndex = pickWithStyle();
|
|
53607
53812
|
if (firstIndex >= 0) {
|
|
53608
53813
|
setBoundedMap(fontState.fontPickCache, cacheKey, firstIndex, FONT_PICK_CACHE_LIMIT);
|
|
53609
53814
|
return firstIndex;
|
|
@@ -53611,6 +53816,24 @@ function createResttyApp(options) {
|
|
|
53611
53816
|
setBoundedMap(fontState.fontPickCache, cacheKey, 0, FONT_PICK_CACHE_LIMIT);
|
|
53612
53817
|
return 0;
|
|
53613
53818
|
}
|
|
53819
|
+
function stylePreferenceFromFlags(bold, italic) {
|
|
53820
|
+
if (bold && italic)
|
|
53821
|
+
return "bold_italic";
|
|
53822
|
+
if (bold)
|
|
53823
|
+
return "bold";
|
|
53824
|
+
if (italic)
|
|
53825
|
+
return "italic";
|
|
53826
|
+
return "regular";
|
|
53827
|
+
}
|
|
53828
|
+
function isAppleSymbolsFont(entry) {
|
|
53829
|
+
return !!entry && /\bapple symbols\b/i.test(entry.label ?? "");
|
|
53830
|
+
}
|
|
53831
|
+
function fontEntryHasBoldStyle(entry) {
|
|
53832
|
+
return !!entry && /\bbold\b/i.test(entry.label ?? "");
|
|
53833
|
+
}
|
|
53834
|
+
function fontEntryHasItalicStyle(entry) {
|
|
53835
|
+
return !!entry && /\b(italic|oblique)\b/i.test(entry.label ?? "");
|
|
53836
|
+
}
|
|
53614
53837
|
function computeCellMetrics2() {
|
|
53615
53838
|
const primary = fontState.fonts[0];
|
|
53616
53839
|
if (!primary)
|
|
@@ -54319,7 +54542,7 @@ function createResttyApp(options) {
|
|
|
54319
54542
|
}
|
|
54320
54543
|
if (extra > 0 && text.trim() === "")
|
|
54321
54544
|
continue;
|
|
54322
|
-
const fontIndex = pickFontIndexForText2(text, baseSpan);
|
|
54545
|
+
const fontIndex = pickFontIndexForText2(text, baseSpan, stylePreferenceFromFlags(bold, italic));
|
|
54323
54546
|
const fontEntry = fontState.fonts[fontIndex] ?? fontState.fonts[0];
|
|
54324
54547
|
const shaped = shapeClusterWithFont(fontEntry, text);
|
|
54325
54548
|
if (!shaped.glyphs.length)
|
|
@@ -54588,7 +54811,8 @@ function createResttyApp(options) {
|
|
|
54588
54811
|
let y = item.baseY + baselineAdjust - metrics.bearingY * bitmapScale - glyph.yOffset * itemScale;
|
|
54589
54812
|
if (!glyphConstrained && symbolLike && item.cp) {
|
|
54590
54813
|
const nerdConstraint = resolveSymbolConstraint(item.cp);
|
|
54591
|
-
const
|
|
54814
|
+
const defaultConstraint = isAppleSymbolsFont(entry) ? DEFAULT_APPLE_SYMBOLS_CONSTRAINT : DEFAULT_SYMBOL_CONSTRAINT;
|
|
54815
|
+
const constraint = nerdConstraint ?? (colorGlyph ? DEFAULT_EMOJI_CONSTRAINT : defaultConstraint);
|
|
54592
54816
|
const rowY = item.baseY - yPad - baselineOffset;
|
|
54593
54817
|
const constraintWidth = Math.max(1, item.constraintWidth ?? Math.round(maxWidth / cellW));
|
|
54594
54818
|
const adjusted = constrainGlyphBox({
|
|
@@ -54625,17 +54849,24 @@ function createResttyApp(options) {
|
|
|
54625
54849
|
const glyphData = useNearest ? glyphDataNearest : glyphDataLinear;
|
|
54626
54850
|
const italic = !!item.italic;
|
|
54627
54851
|
const bold = !!item.bold;
|
|
54628
|
-
const
|
|
54629
|
-
const
|
|
54852
|
+
const syntheticItalic = italic && !fontEntryHasItalicStyle(entry);
|
|
54853
|
+
const syntheticBold = bold && !fontEntryHasBoldStyle(entry);
|
|
54854
|
+
const slant = syntheticItalic && !colorGlyph ? gh * ITALIC_SLANT : 0;
|
|
54855
|
+
const boldOffset = syntheticBold && !colorGlyph ? Math.max(1, Math.round(gw * BOLD_OFFSET)) : 0;
|
|
54630
54856
|
const renderMode = colorGlyph ? GLYPH_RENDER_MODE_COLOR : GLYPH_RENDER_MODE_MONO;
|
|
54631
54857
|
const pushGlyph = (xPos) => {
|
|
54632
54858
|
glyphData.push(xPos, py, gw, gh, u02, v02, u12, v12, item.fg[0], item.fg[1], item.fg[2], item.fg[3], bg[0], bg[1], bg[2], bg[3], slant, renderMode);
|
|
54633
54859
|
};
|
|
54634
54860
|
pushGlyph(px);
|
|
54635
54861
|
if (boldOffset > 0) {
|
|
54636
|
-
const
|
|
54637
|
-
const
|
|
54638
|
-
|
|
54862
|
+
const minGlyphX = Math.round(item.x);
|
|
54863
|
+
const maxGlyphX = Math.round(item.x + maxWidth - gw);
|
|
54864
|
+
let bx = clamp(px + boldOffset, minGlyphX, maxGlyphX);
|
|
54865
|
+
if (bx === px)
|
|
54866
|
+
bx = clamp(px - boldOffset, minGlyphX, maxGlyphX);
|
|
54867
|
+
if (bx === px)
|
|
54868
|
+
pushGlyph(px);
|
|
54869
|
+
else
|
|
54639
54870
|
pushGlyph(bx);
|
|
54640
54871
|
}
|
|
54641
54872
|
penX += glyph.xAdvance;
|
|
@@ -55177,7 +55408,7 @@ function createResttyApp(options) {
|
|
|
55177
55408
|
}
|
|
55178
55409
|
if (extra > 0 && text.trim() === "")
|
|
55179
55410
|
continue;
|
|
55180
|
-
const fontIndex = pickFontIndexForText2(text, baseSpan);
|
|
55411
|
+
const fontIndex = pickFontIndexForText2(text, baseSpan, stylePreferenceFromFlags(bold, italic));
|
|
55181
55412
|
const fontEntry = fontState.fonts[fontIndex] ?? fontState.fonts[0];
|
|
55182
55413
|
const shaped = shapeClusterWithFont(fontEntry, text);
|
|
55183
55414
|
if (!shaped.glyphs.length)
|
|
@@ -55547,7 +55778,8 @@ function createResttyApp(options) {
|
|
|
55547
55778
|
let y = item.baseY + baselineAdjust - metrics.bearingY * bitmapScale - glyph.yOffset * itemScale;
|
|
55548
55779
|
if (!glyphConstrained && symbolLike && item.cp) {
|
|
55549
55780
|
const nerdConstraint = resolveSymbolConstraint(item.cp);
|
|
55550
|
-
const
|
|
55781
|
+
const defaultConstraint = isAppleSymbolsFont(entry) ? DEFAULT_APPLE_SYMBOLS_CONSTRAINT : DEFAULT_SYMBOL_CONSTRAINT;
|
|
55782
|
+
const constraint = nerdConstraint ?? (colorGlyph ? DEFAULT_EMOJI_CONSTRAINT : defaultConstraint);
|
|
55551
55783
|
const rowY = item.baseY - yPad - baselineOffset;
|
|
55552
55784
|
const constraintWidth = Math.max(1, item.constraintWidth ?? Math.round(maxWidth / cellW));
|
|
55553
55785
|
const adjusted = constrainGlyphBox({
|
|
@@ -55576,17 +55808,24 @@ function createResttyApp(options) {
|
|
|
55576
55808
|
const v12 = (metrics.atlasY + metrics.height - insetY) / atlasH;
|
|
55577
55809
|
const italic = !!item.italic;
|
|
55578
55810
|
const bold = !!item.bold;
|
|
55579
|
-
const
|
|
55580
|
-
const
|
|
55811
|
+
const syntheticItalic = italic && !fontEntryHasItalicStyle(entry);
|
|
55812
|
+
const syntheticBold = bold && !fontEntryHasBoldStyle(entry);
|
|
55813
|
+
const slant = syntheticItalic && !colorGlyph ? gh * ITALIC_SLANT : 0;
|
|
55814
|
+
const boldOffset = syntheticBold && !colorGlyph ? Math.max(1, Math.round(gw * BOLD_OFFSET)) : 0;
|
|
55581
55815
|
const renderMode = colorGlyph ? GLYPH_RENDER_MODE_COLOR : GLYPH_RENDER_MODE_MONO;
|
|
55582
55816
|
const pushGlyph = (xPos) => {
|
|
55583
55817
|
glyphData.push(xPos, py, gw, gh, u02, v02, u12, v12, item.fg[0], item.fg[1], item.fg[2], item.fg[3], bg[0], bg[1], bg[2], bg[3], slant, renderMode);
|
|
55584
55818
|
};
|
|
55585
55819
|
pushGlyph(px);
|
|
55586
55820
|
if (boldOffset > 0) {
|
|
55587
|
-
const
|
|
55588
|
-
const
|
|
55589
|
-
|
|
55821
|
+
const minGlyphX = Math.round(item.x);
|
|
55822
|
+
const maxGlyphX = Math.round(item.x + maxWidth - gw);
|
|
55823
|
+
let bx = clamp(px + boldOffset, minGlyphX, maxGlyphX);
|
|
55824
|
+
if (bx === px)
|
|
55825
|
+
bx = clamp(px - boldOffset, minGlyphX, maxGlyphX);
|
|
55826
|
+
if (bx === px)
|
|
55827
|
+
pushGlyph(px);
|
|
55828
|
+
else
|
|
55590
55829
|
pushGlyph(bx);
|
|
55591
55830
|
}
|
|
55592
55831
|
penX += glyph.xAdvance;
|
package/dist/internal.js
CHANGED
package/dist/restty.js
CHANGED