expo-pretext 0.2.0

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/src/cache.ts ADDED
@@ -0,0 +1,59 @@
1
+ // src/cache.ts
2
+ // JS-side width cache to skip native calls when all segments are cached.
3
+
4
+ const widthCache = new Map<string, Map<string, number>>()
5
+
6
+ export function getCachedWidth(
7
+ fontKey: string,
8
+ segment: string
9
+ ): number | undefined {
10
+ return widthCache.get(fontKey)?.get(segment)
11
+ }
12
+
13
+ export function setCachedWidth(
14
+ fontKey: string,
15
+ segment: string,
16
+ width: number
17
+ ): void {
18
+ let fontCache = widthCache.get(fontKey)
19
+ if (!fontCache) {
20
+ fontCache = new Map()
21
+ widthCache.set(fontKey, fontCache)
22
+ }
23
+ fontCache.set(segment, width)
24
+ }
25
+
26
+ export function cacheNativeResult(
27
+ fontKey: string,
28
+ segments: string[],
29
+ widths: number[]
30
+ ): void {
31
+ let fontCache = widthCache.get(fontKey)
32
+ if (!fontCache) {
33
+ fontCache = new Map()
34
+ widthCache.set(fontKey, fontCache)
35
+ }
36
+ for (let i = 0; i < segments.length; i++) {
37
+ fontCache.set(segments[i]!, widths[i]!)
38
+ }
39
+ }
40
+
41
+ export function tryResolveAllFromCache(
42
+ fontKey: string,
43
+ segments: string[]
44
+ ): number[] | null {
45
+ const fontCache = widthCache.get(fontKey)
46
+ if (!fontCache) return null
47
+
48
+ const widths: number[] = new Array(segments.length)
49
+ for (let i = 0; i < segments.length; i++) {
50
+ const w = fontCache.get(segments[i]!)
51
+ if (w === undefined) return null
52
+ widths[i] = w
53
+ }
54
+ return widths
55
+ }
56
+
57
+ export function clearJSCache(): void {
58
+ widthCache.clear()
59
+ }
@@ -0,0 +1,38 @@
1
+ // src/engine-profile.ts
2
+ import { Platform } from 'react-native'
3
+
4
+ export type EngineProfile = {
5
+ lineFitEpsilon: number
6
+ carryCJKAfterClosingQuote: boolean
7
+ preferPrefixWidthsForBreakableRuns: boolean
8
+ preferEarlySoftHyphenBreak: boolean
9
+ }
10
+
11
+ let cachedProfile: EngineProfile | null = null
12
+
13
+ export function getEngineProfile(): EngineProfile {
14
+ if (cachedProfile !== null) return cachedProfile
15
+
16
+ cachedProfile = Platform.select({
17
+ ios: {
18
+ lineFitEpsilon: 0.01, // restored to default for diagnostic
19
+ carryCJKAfterClosingQuote: true,
20
+ preferPrefixWidthsForBreakableRuns: false,
21
+ preferEarlySoftHyphenBreak: false,
22
+ },
23
+ android: {
24
+ lineFitEpsilon: 0.02,
25
+ carryCJKAfterClosingQuote: false,
26
+ preferPrefixWidthsForBreakableRuns: false,
27
+ preferEarlySoftHyphenBreak: false,
28
+ },
29
+ default: {
30
+ lineFitEpsilon: 0.01,
31
+ carryCJKAfterClosingQuote: false,
32
+ preferPrefixWidthsForBreakableRuns: false,
33
+ preferEarlySoftHyphenBreak: false,
34
+ },
35
+ })!
36
+
37
+ return cachedProfile
38
+ }
@@ -0,0 +1,50 @@
1
+ // src/font-utils.ts
2
+ import type { TextStyle, FontDescriptor } from './types'
3
+
4
+ export function textStyleToFontDescriptor(style: TextStyle): FontDescriptor {
5
+ return {
6
+ fontFamily: style.fontFamily,
7
+ fontSize: style.fontSize,
8
+ fontWeight: style.fontWeight,
9
+ fontStyle: style.fontStyle,
10
+ }
11
+ }
12
+
13
+ export function getFontKey(style: TextStyle): string {
14
+ const weight = style.fontWeight ?? '400'
15
+ const fStyle = style.fontStyle ?? 'normal'
16
+ return `${style.fontFamily}_${style.fontSize}_${weight}_${fStyle}`
17
+ }
18
+
19
+ export function getLineHeight(style: TextStyle): number {
20
+ return style.lineHeight ?? style.fontSize * 1.2
21
+ }
22
+
23
+ const SYSTEM_FONTS = [
24
+ 'System', 'system', 'sans-serif', 'serif', 'monospace',
25
+ // iOS built-in fonts
26
+ 'Helvetica', 'Helvetica Neue', 'Arial', 'Courier', 'Courier New',
27
+ 'Georgia', 'Times New Roman', 'Trebuchet MS', 'Verdana',
28
+ 'American Typewriter', 'Avenir', 'Avenir Next', 'Baskerville',
29
+ 'Didot', 'Futura', 'Gill Sans', 'Menlo', 'Optima', 'Palatino',
30
+ ]
31
+
32
+ export function isFontLoaded(fontFamily: string): boolean {
33
+ // System fonts are always available
34
+ if (SYSTEM_FONTS.includes(fontFamily)) return true
35
+ try {
36
+ const Font = require('expo-font')
37
+ return Font.isLoaded(fontFamily)
38
+ } catch {
39
+ return true
40
+ }
41
+ }
42
+
43
+ export function warnIfFontNotLoaded(style: TextStyle): void {
44
+ if (__DEV__ && !isFontLoaded(style.fontFamily)) {
45
+ console.warn(
46
+ `[expo-pretext] Font "${style.fontFamily}" not loaded. ` +
47
+ `Heights will be inaccurate. Use Font.loadAsync() first.`
48
+ )
49
+ }
50
+ }