@glassly/miniapp 0.3.0-dev.2 → 0.3.0-dev.462

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.
Files changed (255) hide show
  1. package/README.md +219 -74
  2. package/dist/background/index.d.ts +14 -8
  3. package/dist/background/index.d.ts.map +1 -1
  4. package/dist/background/index.js +4 -0
  5. package/dist/background/index.js.map +1 -1
  6. package/dist/background/register.d.ts +1 -1
  7. package/dist/background/register.js +1 -1
  8. package/dist/display/index.d.ts +23 -0
  9. package/dist/display/index.d.ts.map +1 -0
  10. package/dist/display/index.js +17 -0
  11. package/dist/display/index.js.map +1 -0
  12. package/dist/display/measurer/TextMeasurer.d.ts +160 -0
  13. package/dist/display/measurer/TextMeasurer.d.ts.map +1 -0
  14. package/dist/display/measurer/TextMeasurer.js +272 -0
  15. package/dist/display/measurer/TextMeasurer.js.map +1 -0
  16. package/dist/display/measurer/index.d.ts +10 -0
  17. package/dist/display/measurer/index.d.ts.map +1 -0
  18. package/dist/display/measurer/index.js +11 -0
  19. package/dist/display/measurer/index.js.map +1 -0
  20. package/dist/display/measurer/script-detection.d.ts +53 -0
  21. package/dist/display/measurer/script-detection.d.ts.map +1 -0
  22. package/dist/display/measurer/script-detection.js +184 -0
  23. package/dist/display/measurer/script-detection.js.map +1 -0
  24. package/dist/display/pixelArt.d.ts +22 -0
  25. package/dist/display/pixelArt.d.ts.map +1 -0
  26. package/dist/display/pixelArt.js +126 -0
  27. package/dist/display/pixelArt.js.map +1 -0
  28. package/dist/display/profiles/g1.d.ts +33 -0
  29. package/dist/display/profiles/g1.d.ts.map +1 -0
  30. package/dist/display/profiles/g1.js +214 -0
  31. package/dist/display/profiles/g1.js.map +1 -0
  32. package/dist/display/profiles/g2.d.ts +13 -0
  33. package/dist/display/profiles/g2.d.ts.map +1 -0
  34. package/dist/display/profiles/g2.js +34 -0
  35. package/dist/display/profiles/g2.js.map +1 -0
  36. package/dist/display/profiles/index.d.ts +12 -0
  37. package/dist/display/profiles/index.d.ts.map +1 -0
  38. package/dist/display/profiles/index.js +15 -0
  39. package/dist/display/profiles/index.js.map +1 -0
  40. package/dist/display/profiles/nex.d.ts +10 -0
  41. package/dist/display/profiles/nex.d.ts.map +1 -0
  42. package/dist/display/profiles/nex.js +150 -0
  43. package/dist/display/profiles/nex.js.map +1 -0
  44. package/dist/display/profiles/types.d.ts +103 -0
  45. package/dist/display/profiles/types.d.ts.map +1 -0
  46. package/dist/display/profiles/types.js +2 -0
  47. package/dist/display/profiles/types.js.map +1 -0
  48. package/dist/display/profiles/z100.d.ts +33 -0
  49. package/dist/display/profiles/z100.d.ts.map +1 -0
  50. package/dist/display/profiles/z100.js +182 -0
  51. package/dist/display/profiles/z100.js.map +1 -0
  52. package/dist/display/scene/types.d.ts +292 -0
  53. package/dist/display/scene/types.d.ts.map +1 -0
  54. package/dist/display/scene/types.js +0 -0
  55. package/dist/display/scene/types.js.map +1 -0
  56. package/dist/display/wrapper/TextWrapper.d.ts +102 -0
  57. package/dist/display/wrapper/TextWrapper.d.ts.map +1 -0
  58. package/dist/display/wrapper/TextWrapper.js +469 -0
  59. package/dist/display/wrapper/TextWrapper.js.map +1 -0
  60. package/dist/display/wrapper/index.d.ts +12 -0
  61. package/dist/display/wrapper/index.d.ts.map +1 -0
  62. package/dist/display/wrapper/index.js +12 -0
  63. package/dist/display/wrapper/index.js.map +1 -0
  64. package/dist/display/wrapper/types.d.ts +75 -0
  65. package/dist/display/wrapper/types.d.ts.map +1 -0
  66. package/dist/display/wrapper/types.js +11 -0
  67. package/dist/display/wrapper/types.js.map +1 -0
  68. package/dist/globals.d.ts +5 -5
  69. package/dist/globals.d.ts.map +1 -1
  70. package/dist/globals.js +1 -1
  71. package/dist/globals.js.map +1 -1
  72. package/dist/hardware.d.ts +4 -18
  73. package/dist/hardware.d.ts.map +1 -1
  74. package/dist/hardware.js +2 -13
  75. package/dist/hardware.js.map +1 -1
  76. package/dist/index.d.ts +16 -10
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +3 -1
  79. package/dist/index.js.map +1 -1
  80. package/dist/knownApps.d.ts +26 -0
  81. package/dist/knownApps.d.ts.map +1 -0
  82. package/dist/knownApps.js +140 -0
  83. package/dist/knownApps.js.map +1 -0
  84. package/dist/mirror/canvas.d.ts +22 -0
  85. package/dist/mirror/canvas.d.ts.map +1 -0
  86. package/dist/mirror/canvas.js +311 -0
  87. package/dist/mirror/canvas.js.map +1 -0
  88. package/dist/mirror/geometry.d.ts +69 -0
  89. package/dist/mirror/geometry.d.ts.map +1 -0
  90. package/dist/mirror/geometry.js +75 -0
  91. package/dist/mirror/geometry.js.map +1 -0
  92. package/dist/mirror/index.d.ts +3 -0
  93. package/dist/mirror/index.d.ts.map +1 -0
  94. package/dist/mirror/index.js +2 -0
  95. package/dist/mirror/index.js.map +1 -0
  96. package/dist/mirror/types.d.ts +40 -0
  97. package/dist/mirror/types.d.ts.map +1 -0
  98. package/dist/mirror/types.js +2 -0
  99. package/dist/mirror/types.js.map +1 -0
  100. package/dist/modules/auth.d.ts +1 -1
  101. package/dist/modules/auth.d.ts.map +1 -1
  102. package/dist/modules/auth.js +2 -2
  103. package/dist/modules/auth.js.map +1 -1
  104. package/dist/modules/compass.d.ts +47 -0
  105. package/dist/modules/compass.d.ts.map +1 -0
  106. package/dist/modules/compass.js +39 -0
  107. package/dist/modules/compass.js.map +1 -0
  108. package/dist/modules/display.d.ts +192 -8
  109. package/dist/modules/display.d.ts.map +1 -1
  110. package/dist/modules/display.js +40 -3
  111. package/dist/modules/display.js.map +1 -1
  112. package/dist/modules/events.d.ts +30 -2
  113. package/dist/modules/events.d.ts.map +1 -1
  114. package/dist/modules/events.js.map +1 -1
  115. package/dist/modules/input.d.ts +40 -1
  116. package/dist/modules/input.d.ts.map +1 -1
  117. package/dist/modules/input.js +45 -1
  118. package/dist/modules/input.js.map +1 -1
  119. package/dist/modules/latest-render-scheduler.d.ts +19 -0
  120. package/dist/modules/latest-render-scheduler.d.ts.map +1 -0
  121. package/dist/modules/latest-render-scheduler.js +54 -0
  122. package/dist/modules/latest-render-scheduler.js.map +1 -0
  123. package/dist/modules/lightSensor.d.ts +44 -0
  124. package/dist/modules/lightSensor.d.ts.map +1 -0
  125. package/dist/modules/lightSensor.js +33 -0
  126. package/dist/modules/lightSensor.js.map +1 -0
  127. package/dist/modules/mic.d.ts +3 -2
  128. package/dist/modules/mic.d.ts.map +1 -1
  129. package/dist/modules/mic.js +3 -2
  130. package/dist/modules/mic.js.map +1 -1
  131. package/dist/modules/miniapps.d.ts +2 -0
  132. package/dist/modules/miniapps.d.ts.map +1 -1
  133. package/dist/modules/miniapps.js.map +1 -1
  134. package/dist/modules/mirror.d.ts +16 -0
  135. package/dist/modules/mirror.d.ts.map +1 -0
  136. package/dist/modules/mirror.js +40 -0
  137. package/dist/modules/mirror.js.map +1 -0
  138. package/dist/modules/mono-text-rows.d.ts +20 -0
  139. package/dist/modules/mono-text-rows.d.ts.map +1 -0
  140. package/dist/modules/mono-text-rows.js +26 -0
  141. package/dist/modules/mono-text-rows.js.map +1 -0
  142. package/dist/modules/navigation.d.ts.map +1 -1
  143. package/dist/modules/navigation.js +21 -14
  144. package/dist/modules/navigation.js.map +1 -1
  145. package/dist/modules/phone.d.ts +26 -1
  146. package/dist/modules/phone.d.ts.map +1 -1
  147. package/dist/modules/phone.js +28 -0
  148. package/dist/modules/phone.js.map +1 -1
  149. package/dist/modules/settings.d.ts +45 -0
  150. package/dist/modules/settings.d.ts.map +1 -0
  151. package/dist/modules/settings.js +54 -0
  152. package/dist/modules/settings.js.map +1 -0
  153. package/dist/modules/system.d.ts +21 -0
  154. package/dist/modules/system.d.ts.map +1 -1
  155. package/dist/modules/system.js +12 -0
  156. package/dist/modules/system.js.map +1 -1
  157. package/dist/modules/transcription.d.ts +3 -2
  158. package/dist/modules/transcription.d.ts.map +1 -1
  159. package/dist/modules/transcription.js +3 -2
  160. package/dist/modules/transcription.js.map +1 -1
  161. package/dist/protocol.d.ts +65 -5
  162. package/dist/protocol.d.ts.map +1 -1
  163. package/dist/protocol.js +66 -5
  164. package/dist/protocol.js.map +1 -1
  165. package/dist/react/MirrorCanvas.d.ts +10 -0
  166. package/dist/react/MirrorCanvas.d.ts.map +1 -0
  167. package/dist/react/MirrorCanvas.js +23 -0
  168. package/dist/react/MirrorCanvas.js.map +1 -0
  169. package/dist/react/index.d.ts +2 -0
  170. package/dist/react/index.d.ts.map +1 -1
  171. package/dist/react/index.js +1 -0
  172. package/dist/react/index.js.map +1 -1
  173. package/dist/react/useColorScheme.d.ts +2 -3
  174. package/dist/react/useColorScheme.d.ts.map +1 -1
  175. package/dist/react/useColorScheme.js +15 -8
  176. package/dist/react/useColorScheme.js.map +1 -1
  177. package/dist/react/useRpc.js +2 -2
  178. package/dist/react/useRpc.js.map +1 -1
  179. package/dist/react/useSafeArea.d.ts.map +1 -1
  180. package/dist/react/useSafeArea.js +2 -2
  181. package/dist/react/useSafeArea.js.map +1 -1
  182. package/dist/session.d.ts +50 -4
  183. package/dist/session.d.ts.map +1 -1
  184. package/dist/session.js +35 -6
  185. package/dist/session.js.map +1 -1
  186. package/dist/transport/auto.d.ts +2 -2
  187. package/dist/transport/auto.js +2 -2
  188. package/dist/transport/dispatch.d.ts +1 -1
  189. package/dist/transport/dispatch.js +1 -1
  190. package/dist/transport/mock.d.ts +4 -4
  191. package/dist/transport/mock.d.ts.map +1 -1
  192. package/dist/transport/mock.js +31 -7
  193. package/dist/transport/mock.js.map +1 -1
  194. package/dist/ui/index.d.ts +2 -0
  195. package/dist/ui/index.d.ts.map +1 -1
  196. package/dist/ui/index.js +1 -0
  197. package/dist/ui/index.js.map +1 -1
  198. package/package.json +19 -3
  199. package/src/background/index.ts +26 -4
  200. package/src/background/register.ts +1 -1
  201. package/src/display/index.ts +83 -0
  202. package/src/display/measurer/TextMeasurer.ts +346 -0
  203. package/src/display/measurer/index.ts +21 -0
  204. package/src/display/measurer/script-detection.ts +218 -0
  205. package/src/display/pixelArt.ts +141 -0
  206. package/src/display/profiles/g1.ts +237 -0
  207. package/src/display/profiles/g2.ts +39 -0
  208. package/src/display/profiles/index.ts +28 -0
  209. package/src/display/profiles/nex.ts +166 -0
  210. package/src/display/profiles/types.ts +132 -0
  211. package/src/display/profiles/z100.ts +198 -0
  212. package/src/display/scene/types.ts +335 -0
  213. package/src/display/wrapper/TextWrapper.ts +546 -0
  214. package/src/display/wrapper/index.ts +15 -0
  215. package/src/display/wrapper/types.ts +102 -0
  216. package/src/globals.ts +5 -5
  217. package/src/hardware.ts +6 -21
  218. package/src/index.ts +34 -6
  219. package/src/knownApps.ts +170 -0
  220. package/src/mirror/canvas.ts +322 -0
  221. package/src/mirror/geometry.ts +128 -0
  222. package/src/mirror/index.ts +2 -0
  223. package/src/mirror/types.ts +38 -0
  224. package/src/modules/auth.ts +2 -2
  225. package/src/modules/compass.ts +69 -0
  226. package/src/modules/display.ts +222 -12
  227. package/src/modules/events.ts +27 -1
  228. package/src/modules/input.ts +55 -2
  229. package/src/modules/latest-render-scheduler.ts +55 -0
  230. package/src/modules/lightSensor.ts +61 -0
  231. package/src/modules/mic.ts +3 -2
  232. package/src/modules/miniapps.ts +2 -0
  233. package/src/modules/mirror.ts +42 -0
  234. package/src/modules/mono-text-rows.ts +30 -0
  235. package/src/modules/navigation.ts +20 -14
  236. package/src/modules/phone.ts +40 -1
  237. package/src/modules/settings.ts +64 -0
  238. package/src/modules/system.ts +30 -1
  239. package/src/modules/transcription.ts +3 -2
  240. package/src/protocol.ts +72 -5
  241. package/src/react/MirrorCanvas.tsx +35 -0
  242. package/src/react/index.ts +3 -0
  243. package/src/react/useColorScheme.ts +17 -8
  244. package/src/react/useRpc.ts +2 -2
  245. package/src/react/useSafeArea.ts +2 -2
  246. package/src/session.ts +78 -8
  247. package/src/transport/auto.ts +2 -2
  248. package/src/transport/dispatch.ts +1 -1
  249. package/src/transport/mock.ts +42 -11
  250. package/src/ui/index.ts +3 -0
  251. package/dist/modules/heading.d.ts +0 -16
  252. package/dist/modules/heading.d.ts.map +0 -1
  253. package/dist/modules/heading.js +0 -20
  254. package/dist/modules/heading.js.map +0 -1
  255. package/src/modules/heading.ts +0 -23
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Unicode ranges for script detection.
3
+ * Used to classify characters for proper width measurement.
4
+ */
5
+ export const SCRIPT_RANGES = {
6
+ // CJK Unified Ideographs
7
+ cjk: [
8
+ [0x4e00, 0x9fff], // Main block (common Chinese, Japanese Kanji)
9
+ [0x3400, 0x4dbf], // Extension A
10
+ [0x20000, 0x2a6df], // Extension B
11
+ [0x2a700, 0x2b73f], // Extension C
12
+ [0x2b740, 0x2b81f], // Extension D
13
+ [0xf900, 0xfaff], // Compatibility Ideographs
14
+ ],
15
+ // Japanese Hiragana
16
+ hiragana: [[0x3040, 0x309f]],
17
+ // Japanese Katakana
18
+ katakana: [
19
+ [0x30a0, 0x30ff], // Main block
20
+ [0x31f0, 0x31ff], // Phonetic Extensions
21
+ ],
22
+ // Korean
23
+ korean: [
24
+ [0xac00, 0xd7af], // Hangul Syllables
25
+ [0x1100, 0x11ff], // Hangul Jamo
26
+ [0x3130, 0x318f], // Compatibility Jamo
27
+ [0xa960, 0xa97f], // Jamo Extended-A
28
+ [0xd7b0, 0xd7ff], // Jamo Extended-B
29
+ ],
30
+ // Cyrillic
31
+ cyrillic: [
32
+ [0x0400, 0x04ff], // Main block
33
+ [0x0500, 0x052f], // Supplement
34
+ ],
35
+ // Numbers (ASCII)
36
+ numbers: [[0x30, 0x39]],
37
+ // Basic punctuation (ASCII)
38
+ punctuation: [
39
+ [0x20, 0x2f], // Space and basic punctuation
40
+ [0x3a, 0x40], // More punctuation
41
+ [0x5b, 0x60], // Brackets etc.
42
+ [0x7b, 0x7e], // Braces etc.
43
+ ],
44
+ // Unsupported scripts (for filtering)
45
+ arabic: [[0x0600, 0x06ff]],
46
+ hebrew: [[0x0590, 0x05ff]],
47
+ thai: [[0x0e00, 0x0e7f]],
48
+ emoji: [
49
+ [0x1f600, 0x1f64f], // Emoticons
50
+ [0x1f300, 0x1f5ff], // Misc Symbols and Pictographs
51
+ [0x1f680, 0x1f6ff], // Transport and Map
52
+ [0x1f1e0, 0x1f1ff], // Flags
53
+ [0x2600, 0x26ff], // Misc Symbols
54
+ [0x2700, 0x27bf], // Dingbats
55
+ [0xfe00, 0xfe0f], // Variation Selectors
56
+ [0x1f900, 0x1f9ff], // Supplemental Symbols
57
+ ],
58
+ };
59
+ /**
60
+ * Check if a code point is within any of the given ranges.
61
+ */
62
+ function inRanges(codePoint, ranges) {
63
+ for (const [start, end] of ranges) {
64
+ if (codePoint >= start && codePoint <= end) {
65
+ return true;
66
+ }
67
+ }
68
+ return false;
69
+ }
70
+ /**
71
+ * Detect the script type of a single character.
72
+ *
73
+ * @param char - Single character to classify
74
+ * @returns The script type of the character
75
+ */
76
+ export function detectScript(char) {
77
+ if (!char || char.length === 0) {
78
+ return "latin";
79
+ }
80
+ // Get the code point (handles surrogate pairs for characters outside BMP)
81
+ const codePoint = char.codePointAt(0);
82
+ if (codePoint === undefined) {
83
+ return "latin";
84
+ }
85
+ // Check each script in order of likelihood/importance
86
+ // CJK (most common for multi-byte)
87
+ if (inRanges(codePoint, SCRIPT_RANGES.cjk)) {
88
+ return "cjk";
89
+ }
90
+ // Japanese kana
91
+ if (inRanges(codePoint, SCRIPT_RANGES.hiragana)) {
92
+ return "hiragana";
93
+ }
94
+ if (inRanges(codePoint, SCRIPT_RANGES.katakana)) {
95
+ return "katakana";
96
+ }
97
+ // Korean
98
+ if (inRanges(codePoint, SCRIPT_RANGES.korean)) {
99
+ return "korean";
100
+ }
101
+ // Cyrillic
102
+ if (inRanges(codePoint, SCRIPT_RANGES.cyrillic)) {
103
+ return "cyrillic";
104
+ }
105
+ // Numbers
106
+ if (inRanges(codePoint, SCRIPT_RANGES.numbers)) {
107
+ return "numbers";
108
+ }
109
+ // Punctuation
110
+ if (inRanges(codePoint, SCRIPT_RANGES.punctuation)) {
111
+ return "punctuation";
112
+ }
113
+ // Unsupported scripts
114
+ if (inRanges(codePoint, SCRIPT_RANGES.arabic) ||
115
+ inRanges(codePoint, SCRIPT_RANGES.hebrew) ||
116
+ inRanges(codePoint, SCRIPT_RANGES.thai) ||
117
+ inRanges(codePoint, SCRIPT_RANGES.emoji)) {
118
+ return "unsupported";
119
+ }
120
+ // Default to Latin for ASCII letters and anything else
121
+ return "latin";
122
+ }
123
+ /**
124
+ * Check if a character is a CJK character (Chinese, Japanese Kanji).
125
+ * CJK characters can break anywhere without needing a hyphen.
126
+ */
127
+ export function isCJKCharacter(char) {
128
+ const script = detectScript(char);
129
+ return script === "cjk" || script === "hiragana" || script === "katakana";
130
+ }
131
+ /**
132
+ * Check if a character is Korean Hangul.
133
+ */
134
+ export function isKoreanCharacter(char) {
135
+ return detectScript(char) === "korean";
136
+ }
137
+ /**
138
+ * Check if a character is from a uniform-width script.
139
+ * These scripts render all characters at the same width.
140
+ */
141
+ export function isUniformWidthScript(char) {
142
+ const script = detectScript(char);
143
+ return (script === "cjk" || script === "hiragana" || script === "katakana" || script === "korean" || script === "cyrillic");
144
+ }
145
+ /**
146
+ * Check if a character is from an unsupported script.
147
+ * These characters may not render correctly on the glasses.
148
+ */
149
+ export function isUnsupportedScript(char) {
150
+ return detectScript(char) === "unsupported";
151
+ }
152
+ /**
153
+ * Check if breaking between two characters requires a hyphen.
154
+ * Returns false for:
155
+ * - Breaking after CJK characters (can break anywhere)
156
+ * - Breaking before or after spaces
157
+ * - Breaking after punctuation
158
+ */
159
+ export function needsHyphenForBreak(charBefore, charAfter) {
160
+ // No hyphen needed after CJK (can break anywhere)
161
+ if (isCJKCharacter(charBefore)) {
162
+ return false;
163
+ }
164
+ // No hyphen needed before CJK
165
+ if (isCJKCharacter(charAfter)) {
166
+ return false;
167
+ }
168
+ // No hyphen needed after space
169
+ if (charBefore === " " || charBefore === "\t") {
170
+ return false;
171
+ }
172
+ // No hyphen needed before space (the space is a natural break point)
173
+ if (charAfter === " " || charAfter === "\t") {
174
+ return false;
175
+ }
176
+ // No hyphen needed after existing punctuation that serves as break
177
+ const breakPunctuation = ["-", "–", "—", "/", "\\", "|"];
178
+ if (breakPunctuation.includes(charBefore)) {
179
+ return false;
180
+ }
181
+ // Default: hyphen is needed for mid-word Latin breaks
182
+ return true;
183
+ }
184
+ //# sourceMappingURL=script-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script-detection.js","sourceRoot":"","sources":["../../../src/display/measurer/script-detection.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,yBAAyB;IACzB,GAAG,EAAE;QACH,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,8CAA8C;QAChE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc;QAChC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc;QAClC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc;QAClC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc;QAClC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,2BAA2B;KACrC;IAEV,oBAAoB;IACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAU;IAErC,oBAAoB;IACpB,QAAQ,EAAE;QACR,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa;QAC/B,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,sBAAsB;KAChC;IAEV,SAAS;IACT,MAAM,EAAE;QACN,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,mBAAmB;QACrC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc;QAChC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,qBAAqB;QACvC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB;QACpC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB;KAC5B;IAEV,WAAW;IACX,QAAQ,EAAE;QACR,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa;QAC/B,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa;KACvB;IAEV,kBAAkB;IAClB,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAU;IAEhC,4BAA4B;IAC5B,WAAW,EAAE;QACX,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,8BAA8B;QAC5C,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,mBAAmB;QACjC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,gBAAgB;QAC9B,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,cAAc;KACpB;IAEV,sCAAsC;IACtC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAU;IACnC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAU;IACnC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAU;IACjC,KAAK,EAAE;QACL,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY;QAChC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,+BAA+B;QACnD,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB;QACxC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ;QAC5B,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe;QACjC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW;QAC7B,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,sBAAsB;QACxC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,uBAAuB;KACnC;CACF,CAAA;AAEV;;GAEG;AACH,SAAS,QAAQ,CAAC,SAAiB,EAAE,MAA8C;IACjF,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;QAClC,IAAI,SAAS,IAAI,KAAK,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,0EAA0E;IAC1E,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;IACrC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,sDAAsD;IAEtD,mCAAmC;IACnC,IAAI,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,gBAAgB;IAChB,IAAI,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChD,OAAO,UAAU,CAAA;IACnB,CAAC;IACD,IAAI,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChD,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,SAAS;IACT,IAAI,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9C,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,WAAW;IACX,IAAI,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChD,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,UAAU;IACV,IAAI,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/C,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,cAAc;IACd,IAAI,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;QACnD,OAAO,aAAa,CAAA;IACtB,CAAC;IAED,sBAAsB;IACtB,IACE,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC;QACzC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC;QACzC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,IAAI,CAAC;QACvC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,EACxC,CAAC;QACD,OAAO,aAAa,CAAA;IACtB,CAAC;IAED,uDAAuD;IACvD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;IACjC,OAAO,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,UAAU,CAAA;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAA;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;IACjC,OAAO,CACL,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,UAAU,CACnH,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,aAAa,CAAA;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB,EAAE,SAAiB;IACvE,kDAAkD;IAClD,IAAI,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,8BAA8B;IAC9B,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,+BAA+B;IAC/B,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,qEAAqE;IACrE,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,mEAAmE;IACnE,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;IACxD,IAAI,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,sDAAsD;IACtD,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Pixel-art icons for scene `image` elements.
3
+ *
4
+ * An icon is a list of equal-length rows, one character per pixel: "." is
5
+ * black (gray 0), "#" is full ink (15), and a hex digit is that gray level.
6
+ * The rows encode to a grayscale PNG once per icon (base64, memoized by
7
+ * identity), so every element built from the same rows carries byte-identical
8
+ * `data` and the glasses cache one texture for all of them.
9
+ */
10
+ import type { SceneElementInput } from "./scene/types";
11
+ export type PixelArt = readonly string[];
12
+ export declare function pixelArtSize(rows: PixelArt): {
13
+ w: number;
14
+ h: number;
15
+ };
16
+ /** Gray level 0..15 of one pixel character. */
17
+ export declare function pixelLevel(ch: string): number;
18
+ /** The icon as a base64 8-bit grayscale PNG. */
19
+ export declare function pixelArtPng(rows: PixelArt): string;
20
+ /** An image element drawing `rows` with its top-left at (x, y); `color` is the ink level (absent = full). */
21
+ export declare function pixelArtElement(id: string, rows: PixelArt, x: number, y: number, color?: number): SceneElementInput;
22
+ //# sourceMappingURL=pixelArt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pixelArt.d.ts","sourceRoot":"","sources":["../../src/display/pixelArt.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAA;AAEpD,MAAM,MAAM,QAAQ,GAAG,SAAS,MAAM,EAAE,CAAA;AAIxC,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAC,CAEnE;AAED,+CAA+C;AAC/C,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAM7C;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAclD;AAED,6GAA6G;AAC7G,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB,CASnH"}
@@ -0,0 +1,126 @@
1
+ const encoded = new WeakMap();
2
+ export function pixelArtSize(rows) {
3
+ return { w: rows[0]?.length ?? 0, h: rows.length };
4
+ }
5
+ /** Gray level 0..15 of one pixel character. */
6
+ export function pixelLevel(ch) {
7
+ if (ch === ".")
8
+ return 0;
9
+ if (ch === "#")
10
+ return 15;
11
+ const level = parseInt(ch, 16);
12
+ if (Number.isNaN(level))
13
+ throw new Error(`pixel art: unknown pixel "${ch}"`);
14
+ return level;
15
+ }
16
+ /** The icon as a base64 8-bit grayscale PNG. */
17
+ export function pixelArtPng(rows) {
18
+ const cached = encoded.get(rows);
19
+ if (cached !== undefined)
20
+ return cached;
21
+ const { w, h } = pixelArtSize(rows);
22
+ if (w === 0 || h === 0)
23
+ throw new Error("pixel art: empty icon");
24
+ const raw = new Uint8Array((w + 1) * h);
25
+ rows.forEach((row, y) => {
26
+ if (row.length !== w)
27
+ throw new Error(`pixel art: row ${y} is ${row.length} wide, expected ${w}`);
28
+ for (let x = 0; x < w; x++)
29
+ raw[y * (w + 1) + 1 + x] = pixelLevel(row[x]) * 17;
30
+ });
31
+ const png = encodePng(w, h, raw);
32
+ const out = base64(png);
33
+ encoded.set(rows, out);
34
+ return out;
35
+ }
36
+ /** An image element drawing `rows` with its top-left at (x, y); `color` is the ink level (absent = full). */
37
+ export function pixelArtElement(id, rows, x, y, color) {
38
+ const { w, h } = pixelArtSize(rows);
39
+ return {
40
+ type: "image",
41
+ id,
42
+ box: { x, y, w, h },
43
+ data: pixelArtPng(rows),
44
+ ...(color === undefined ? {} : { style: { color } }),
45
+ };
46
+ }
47
+ // ---- PNG (grayscale, stored deflate) ---------------------------------------
48
+ const CRC_TABLE = (() => {
49
+ const table = new Uint32Array(256);
50
+ for (let n = 0; n < 256; n++) {
51
+ let c = n;
52
+ for (let k = 0; k < 8; k++)
53
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
54
+ table[n] = c >>> 0;
55
+ }
56
+ return table;
57
+ })();
58
+ function crc32(bytes) {
59
+ let c = 0xffffffff;
60
+ for (const b of bytes)
61
+ c = CRC_TABLE[(c ^ b) & 0xff] ^ (c >>> 8);
62
+ return (c ^ 0xffffffff) >>> 0;
63
+ }
64
+ function adler32(bytes) {
65
+ let a = 1;
66
+ let b = 0;
67
+ for (const byte of bytes) {
68
+ a = (a + byte) % 65521;
69
+ b = (b + a) % 65521;
70
+ }
71
+ return ((b << 16) | a) >>> 0;
72
+ }
73
+ function u32(value) {
74
+ return [(value >>> 24) & 0xff, (value >>> 16) & 0xff, (value >>> 8) & 0xff, value & 0xff];
75
+ }
76
+ function chunk(type, body) {
77
+ const typed = [...type].map((ch) => ch.charCodeAt(0));
78
+ const crc = crc32(Uint8Array.from([...typed, ...body]));
79
+ return [...u32(body.length), ...typed, ...body, ...u32(crc)];
80
+ }
81
+ /** zlib stream of stored (uncompressed) blocks, 65535 bytes each at most. */
82
+ function zlibStored(raw) {
83
+ const out = [0x78, 0x01];
84
+ for (let offset = 0; offset < raw.length || offset === 0; offset += 65535) {
85
+ const block = raw.subarray(offset, Math.min(raw.length, offset + 65535));
86
+ const last = offset + block.length >= raw.length;
87
+ out.push(last ? 1 : 0, block.length & 0xff, block.length >>> 8, ~block.length & 0xff, (~block.length >>> 8) & 0xff);
88
+ for (const b of block)
89
+ out.push(b);
90
+ if (last)
91
+ break;
92
+ }
93
+ out.push(...u32(adler32(raw)));
94
+ return out;
95
+ }
96
+ function encodePng(w, h, raw) {
97
+ const header = [...u32(w), ...u32(h), 8, 0, 0, 0, 0]; // 8-bit grayscale, deflate, no interlace
98
+ return Uint8Array.from([
99
+ 0x89,
100
+ 0x50,
101
+ 0x4e,
102
+ 0x47,
103
+ 0x0d,
104
+ 0x0a,
105
+ 0x1a,
106
+ 0x0a,
107
+ ...chunk("IHDR", header),
108
+ ...chunk("IDAT", zlibStored(raw)),
109
+ ...chunk("IEND", []),
110
+ ]);
111
+ }
112
+ const B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
113
+ function base64(bytes) {
114
+ let out = "";
115
+ for (let i = 0; i < bytes.length; i += 3) {
116
+ const a = bytes[i];
117
+ const b = i + 1 < bytes.length ? bytes[i + 1] : 0;
118
+ const c = i + 2 < bytes.length ? bytes[i + 2] : 0;
119
+ const triple = (a << 16) | (b << 8) | c;
120
+ out += B64[(triple >>> 18) & 63] + B64[(triple >>> 12) & 63];
121
+ out += i + 1 < bytes.length ? B64[(triple >>> 6) & 63] : "=";
122
+ out += i + 2 < bytes.length ? B64[triple & 63] : "=";
123
+ }
124
+ return out;
125
+ }
126
+ //# sourceMappingURL=pixelArt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pixelArt.js","sourceRoot":"","sources":["../../src/display/pixelArt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { DisplayProfile } from "./types";
2
+ /**
3
+ * Even Realities G1 Smart Glasses Display Profile
4
+ *
5
+ * Verified through empirical testing with actual hardware.
6
+ * See: line-width-debug-tool/line-width-spec.md
7
+ */
8
+ export declare const G1_PROFILE: DisplayProfile;
9
+ /**
10
+ * G1 Profile for LEGACY mobile clients that have their own wrapping logic.
11
+ *
12
+ * Old mobile clients re-wrap text received from the cloud, causing double-wrapping.
13
+ * This profile uses a reduced display width (~522px instead of 576px) so that
14
+ * when the mobile client re-wraps, the result still fits within 5 lines.
15
+ *
16
+ * Use this profile when:
17
+ * - Mobile client version < X.X.X (has old wrapping logic)
18
+ * - You see text getting cut off or exceeding 5 lines
19
+ *
20
+ * Once all clients are updated, this can be deprecated.
21
+ */
22
+ export declare const G1_PROFILE_LEGACY: DisplayProfile;
23
+ /**
24
+ * Get the hyphen width for G1 in rendered pixels.
25
+ * Hyphen glyph = 4px → rendered = (4+1)*2 = 10px
26
+ */
27
+ export declare const G1_HYPHEN_WIDTH_PX = 10;
28
+ /**
29
+ * Get the space width for G1 in rendered pixels.
30
+ * Space glyph = 2px → rendered = (2+1)*2 = 6px
31
+ */
32
+ export declare const G1_SPACE_WIDTH_PX = 6;
33
+ //# sourceMappingURL=g1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"g1.d.ts","sourceRoot":"","sources":["../../../src/display/profiles/g1.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAA;AAuHtC;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,cAgDxB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAoC/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,IAAI,CAAA"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Complete G1 glyph widths from G1FontLoaderKt
3
+ * These are GLYPH widths - multiply using renderFormula to get rendered pixels.
4
+ * Rendered width = (glyphWidth + 1) * 2
5
+ */
6
+ const G1_GLYPH_WIDTHS = {
7
+ // Punctuation & Symbols
8
+ " ": 2,
9
+ "!": 1,
10
+ '"': 2,
11
+ "#": 6,
12
+ "$": 5,
13
+ "%": 6,
14
+ "&": 7,
15
+ "'": 1,
16
+ "(": 2,
17
+ ")": 2,
18
+ "*": 3,
19
+ "+": 4,
20
+ ",": 1,
21
+ "-": 4, // Hyphen: 4px glyph → 10px rendered (CRITICAL for breaking!)
22
+ ".": 1,
23
+ "/": 3,
24
+ "\u00b7": 1, // Middle dot (notification "sender \u00b7 thread" titles); width assumed to match the period
25
+ // Numbers
26
+ "0": 5,
27
+ "1": 3,
28
+ "2": 5,
29
+ "3": 5,
30
+ "4": 5,
31
+ "5": 5,
32
+ "6": 5,
33
+ "7": 5,
34
+ "8": 5,
35
+ "9": 5,
36
+ // More punctuation
37
+ ":": 1,
38
+ ";": 1,
39
+ "<": 4,
40
+ "=": 4,
41
+ ">": 4,
42
+ "?": 5,
43
+ "@": 7,
44
+ // Uppercase
45
+ "A": 6,
46
+ "B": 5,
47
+ "C": 5,
48
+ "D": 5,
49
+ "E": 4,
50
+ "F": 4,
51
+ "G": 5,
52
+ "H": 5,
53
+ "I": 2,
54
+ "J": 3,
55
+ "K": 5,
56
+ "L": 4,
57
+ "M": 7,
58
+ "N": 5,
59
+ "O": 5,
60
+ "P": 5,
61
+ "Q": 5,
62
+ "R": 5,
63
+ "S": 5,
64
+ "T": 5,
65
+ "U": 5,
66
+ "V": 6,
67
+ "W": 7,
68
+ "X": 6,
69
+ "Y": 6,
70
+ "Z": 5,
71
+ // Brackets & special
72
+ "[": 2,
73
+ "\\": 3,
74
+ "]": 2,
75
+ "^": 4,
76
+ "_": 3,
77
+ "`": 2,
78
+ // Lowercase
79
+ "a": 5,
80
+ "b": 4,
81
+ "c": 4,
82
+ "d": 4,
83
+ "e": 4,
84
+ "f": 4,
85
+ "g": 4,
86
+ "h": 4,
87
+ "i": 1,
88
+ "j": 2,
89
+ "k": 4,
90
+ "l": 1,
91
+ "m": 7,
92
+ "n": 4,
93
+ "o": 4,
94
+ "p": 4,
95
+ "q": 4,
96
+ "r": 3,
97
+ "s": 4,
98
+ "t": 3,
99
+ "u": 5,
100
+ "v": 5,
101
+ "w": 7,
102
+ "x": 5,
103
+ "y": 5,
104
+ "z": 4,
105
+ // More special
106
+ "{": 3,
107
+ "|": 1,
108
+ "}": 3,
109
+ "~": 7,
110
+ };
111
+ /**
112
+ * Even Realities G1 Smart Glasses Display Profile
113
+ *
114
+ * Verified through empirical testing with actual hardware.
115
+ * See: line-width-debug-tool/line-width-spec.md
116
+ */
117
+ export const G1_PROFILE = {
118
+ id: "even-realities-g1",
119
+ name: "Even Realities G1",
120
+ // Display dimensions
121
+ displayWidthPx: 576,
122
+ maxLines: 5,
123
+ // BLE constraints
124
+ maxPayloadBytes: 390,
125
+ bleChunkSize: 176,
126
+ // Font metrics
127
+ fontMetrics: {
128
+ // Glyph widths from G1FontLoaderKt
129
+ glyphWidths: new Map(Object.entries(G1_GLYPH_WIDTHS)),
130
+ // Default glyph width for unmapped Latin characters (use max to be safe)
131
+ defaultGlyphWidth: 7,
132
+ // Rendered width = (glyphWidth + 1) * 2
133
+ renderFormula: (glyphWidth) => (glyphWidth + 1) * 2,
134
+ // Uniform-width scripts - ALL characters in these scripts render at this exact width
135
+ // These are verified values in RENDERED pixels, NOT averages
136
+ uniformScripts: {
137
+ cjk: 18, // ALL Chinese/Japanese Kanji chars = 18px (verified)
138
+ hiragana: 18, // ALL Hiragana chars = 18px (verified)
139
+ katakana: 18, // ALL Katakana chars = 18px (verified)
140
+ korean: 24, // ALL Korean Hangul chars = 24px (verified)
141
+ cyrillic: 18, // ALL Cyrillic chars = 18px (verified)
142
+ },
143
+ // Fallback for unmapped Latin characters
144
+ // Uses MAX width to guarantee no overflow (safe under-utilization)
145
+ fallback: {
146
+ latinMaxWidth: 16, // Max Latin = 'm', 'w' at (7+1)*2 = 16px
147
+ unknownBehavior: "useLatinMax",
148
+ },
149
+ },
150
+ constraints: {
151
+ minCharsBeforeHyphen: 3,
152
+ // Kinsoku: Characters that should not appear at start of line
153
+ noStartChars: [".", ",", "!", "?", ":", ";", ")", "]", "}", "。", ",", "!", "?", ":", ";", ")", "】", "」"],
154
+ // Kinsoku: Characters that should not appear at end of line
155
+ noEndChars: ["(", "[", "{", "(", "【", "「"],
156
+ },
157
+ };
158
+ /**
159
+ * G1 Profile for LEGACY mobile clients that have their own wrapping logic.
160
+ *
161
+ * Old mobile clients re-wrap text received from the cloud, causing double-wrapping.
162
+ * This profile uses a reduced display width (~522px instead of 576px) so that
163
+ * when the mobile client re-wraps, the result still fits within 5 lines.
164
+ *
165
+ * Use this profile when:
166
+ * - Mobile client version < X.X.X (has old wrapping logic)
167
+ * - You see text getting cut off or exceeding 5 lines
168
+ *
169
+ * Once all clients are updated, this can be deprecated.
170
+ */
171
+ export const G1_PROFILE_LEGACY = {
172
+ id: "even-realities-g1-legacy",
173
+ name: "Even Realities G1 (Legacy Client Compatibility)",
174
+ // Reduced display width to prevent double-wrapping overflow
175
+ // Old mobile client wraps at ~90% of true width
176
+ displayWidthPx: 420,
177
+ maxLines: 5,
178
+ // BLE constraints (same as standard)
179
+ maxPayloadBytes: 390,
180
+ bleChunkSize: 176,
181
+ // Font metrics (same as standard)
182
+ fontMetrics: {
183
+ glyphWidths: new Map(Object.entries(G1_GLYPH_WIDTHS)),
184
+ defaultGlyphWidth: 7,
185
+ renderFormula: (glyphWidth) => (glyphWidth + 1) * 2,
186
+ uniformScripts: {
187
+ cjk: 18,
188
+ hiragana: 18,
189
+ katakana: 18,
190
+ korean: 24,
191
+ cyrillic: 18,
192
+ },
193
+ fallback: {
194
+ latinMaxWidth: 16,
195
+ unknownBehavior: "useLatinMax",
196
+ },
197
+ },
198
+ constraints: {
199
+ minCharsBeforeHyphen: 3,
200
+ noStartChars: [".", ",", "!", "?", ":", ";", ")", "]", "}", "。", ",", "!", "?", ":", ";", ")", "】", "」"],
201
+ noEndChars: ["(", "[", "{", "(", "【", "「"],
202
+ },
203
+ };
204
+ /**
205
+ * Get the hyphen width for G1 in rendered pixels.
206
+ * Hyphen glyph = 4px → rendered = (4+1)*2 = 10px
207
+ */
208
+ export const G1_HYPHEN_WIDTH_PX = 10;
209
+ /**
210
+ * Get the space width for G1 in rendered pixels.
211
+ * Space glyph = 2px → rendered = (2+1)*2 = 6px
212
+ */
213
+ export const G1_SPACE_WIDTH_PX = 6;
214
+ //# sourceMappingURL=g1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"g1.js","sourceRoot":"","sources":["../../../src/display/profiles/g1.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { DisplayProfile } from "./types";
2
+ export declare const G2_PROFILE: DisplayProfile;
3
+ /**
4
+ * Get the hyphen width for G2 in rendered pixels.
5
+ * Same as G1: Hyphen glyph = 4px → rendered = (4+1)*2 = 10px
6
+ */
7
+ export declare const G2_HYPHEN_WIDTH_PX = 10;
8
+ /**
9
+ * Get the space width for G2 in rendered pixels.
10
+ * Same as G1: Space glyph = 2px → rendered = (2+1)*2 = 6px
11
+ */
12
+ export declare const G2_SPACE_WIDTH_PX = 6;
13
+ //# sourceMappingURL=g2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"g2.d.ts","sourceRoot":"","sources":["../../../src/display/profiles/g2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAA;AActC,eAAO,MAAM,UAAU,EAAE,cAYxB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,IAAI,CAAA"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Even Realities G2 Smart Glasses Display Profile
3
+ *
4
+ * G2 uses the same display hardware as G1 (green monochrome, ~640x200).
5
+ * Glyph widths and rendering formula are identical to G1.
6
+ * The protocol differs (EvenHub protobuf vs G1 binary) but display
7
+ * characteristics are the same.
8
+ */
9
+ // G2 uses the same glyph widths as G1 (same display hardware/font)
10
+ import { G1_PROFILE } from "./g1";
11
+ export const G2_PROFILE = {
12
+ ...G1_PROFILE,
13
+ id: "even-realities-g2",
14
+ name: "Even Realities G2",
15
+ // G2 fits more vertical text than G1 — allow up to 8 lines before the
16
+ // wrapper truncates (G1 stays at its inherited 5).
17
+ maxLines: 8,
18
+ // Hardware-calibrated 2026-07-03: a 28px container overflowed one line of
19
+ // the firmware font (triggering the fw's overflow indicator tick); 40px is
20
+ // clean. With this set, the scene pipeline height-clips text so a box is
21
+ // never handed more lines than fit.
22
+ lineHeightPx: 40,
23
+ };
24
+ /**
25
+ * Get the hyphen width for G2 in rendered pixels.
26
+ * Same as G1: Hyphen glyph = 4px → rendered = (4+1)*2 = 10px
27
+ */
28
+ export const G2_HYPHEN_WIDTH_PX = 10;
29
+ /**
30
+ * Get the space width for G2 in rendered pixels.
31
+ * Same as G1: Space glyph = 2px → rendered = (2+1)*2 = 6px
32
+ */
33
+ export const G2_SPACE_WIDTH_PX = 6;
34
+ //# sourceMappingURL=g2.js.map