@geastack/core 0.1.24 → 0.1.26
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/events.cpp +2 -0
- package/include/canvas.h +5 -0
- package/include/events.h +2 -1
- package/index.d.ts +26 -8
- package/package.json +4 -4
- package/runtime.cpp +8 -0
- package/scripts/build-gea-vite-geatsc.mjs +190 -93
package/events.cpp
CHANGED
package/include/canvas.h
CHANGED
|
@@ -95,6 +95,11 @@ public:
|
|
|
95
95
|
int width() const;
|
|
96
96
|
int height() const;
|
|
97
97
|
int strideBytes() const;
|
|
98
|
+
// Read or replace one logical framebuffer pixel in native format. Reads are
|
|
99
|
+
// independent of the current clip; writes obey the clip and mark the logical
|
|
100
|
+
// pixel dirty. Writes replace exactly (they do not apply global alpha).
|
|
101
|
+
pixel::native_t readPixelNative(int x, int y) const;
|
|
102
|
+
void writePixelNativeExact(int x, int y, pixel::native_t value);
|
|
98
103
|
|
|
99
104
|
// Software-scroll register: rotates the logical → physical row mapping
|
|
100
105
|
// inside a scroll region without moving any pixels. A pixel write at
|
package/include/events.h
CHANGED
package/index.d.ts
CHANGED
|
@@ -102,10 +102,11 @@ declare global {
|
|
|
102
102
|
* namespace actually defines. `warn`/`info`/`debug` would compile and then
|
|
103
103
|
* fail to link, which is worse than not being declared.
|
|
104
104
|
*/
|
|
105
|
-
|
|
105
|
+
interface Console {
|
|
106
106
|
log(message: string): void
|
|
107
107
|
error(message: string): void
|
|
108
108
|
}
|
|
109
|
+
const console: Console
|
|
109
110
|
|
|
110
111
|
function requestAnimationFrame(callback: (timestampMs: number) => void): number
|
|
111
112
|
|
|
@@ -184,6 +185,8 @@ export type StyleLength =
|
|
|
184
185
|
| `max(${string})`
|
|
185
186
|
| `clamp(${string})`
|
|
186
187
|
export type StyleBox = StyleLength | string
|
|
188
|
+
export type StylePreferredSize = StyleLength | 'auto' | 'min-content' | 'max-content' | 'fit-content'
|
|
189
|
+
export type StyleOverflow = 'visible' | 'hidden' | 'clip' | 'scroll' | 'auto' | 'overlay'
|
|
187
190
|
export type ClassMap = Record<string, string | number | boolean | null | undefined>
|
|
188
191
|
export type ClassValue = string | ClassMap
|
|
189
192
|
|
|
@@ -212,15 +215,27 @@ export interface TouchHost {
|
|
|
212
215
|
export declare const touch: TouchHost
|
|
213
216
|
|
|
214
217
|
export interface Style {
|
|
218
|
+
font?: string
|
|
215
219
|
display?: 'block' | 'flex' | 'grid' | 'none'
|
|
216
|
-
|
|
217
|
-
|
|
220
|
+
visibility?: 'visible' | 'hidden' | 'collapse'
|
|
221
|
+
flexDirection?: 'row' | 'column' | 'row-reverse' | 'column-reverse'
|
|
222
|
+
flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse'
|
|
223
|
+
flexFlow?: string
|
|
224
|
+
boxSizing?: 'content-box' | 'border-box'
|
|
225
|
+
float?: 'none' | 'left' | 'right'
|
|
226
|
+
clear?: 'none' | 'left' | 'right' | 'both'
|
|
227
|
+
writingMode?: 'horizontal-tb' | 'vertical-lr' | 'vertical-rl' | 'sideways-lr' | 'sideways-rl'
|
|
228
|
+
direction?: 'ltr' | 'rtl'
|
|
229
|
+
rowGap?: StyleLength
|
|
230
|
+
columnGap?: StyleLength
|
|
231
|
+
order?: number
|
|
232
|
+
alignContent?: 'flex-start' | 'center' | 'flex-end' | 'stretch' | 'space-between' | 'space-around'
|
|
218
233
|
justifyContent?: 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around'
|
|
219
234
|
alignItems?: 'flex-start' | 'center' | 'flex-end' | 'stretch'
|
|
220
235
|
alignSelf?: 'auto' | 'flex-start' | 'center' | 'flex-end' | 'stretch'
|
|
221
236
|
gap?: StyleLength
|
|
222
|
-
width?:
|
|
223
|
-
height?:
|
|
237
|
+
width?: StylePreferredSize
|
|
238
|
+
height?: StylePreferredSize
|
|
224
239
|
minWidth?: StyleLength
|
|
225
240
|
minHeight?: StyleLength
|
|
226
241
|
maxWidth?: StyleLength
|
|
@@ -256,9 +271,10 @@ export interface Style {
|
|
|
256
271
|
fontFamily?: string
|
|
257
272
|
fontSize?: StyleLength
|
|
258
273
|
textAlign?: 'left' | 'center' | 'right'
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
274
|
+
whiteSpace?: 'normal' | 'nowrap' | 'pre' | 'pre-wrap' | 'pre-line' | 'break-spaces'
|
|
275
|
+
overflow?: StyleOverflow | `${StyleOverflow} ${StyleOverflow}`
|
|
276
|
+
overflowX?: StyleOverflow
|
|
277
|
+
overflowY?: StyleOverflow
|
|
262
278
|
transform?: string | number
|
|
263
279
|
rotate?: string | number
|
|
264
280
|
scale?: string | number
|
|
@@ -444,6 +460,7 @@ export interface GeaEventMap {
|
|
|
444
460
|
input: InputEvent
|
|
445
461
|
keydown: KeyEvent
|
|
446
462
|
rotary: RotaryEvent
|
|
463
|
+
scroll: Event
|
|
447
464
|
}
|
|
448
465
|
|
|
449
466
|
export type TouchEventHandler = (event: TouchEvent) => void
|
|
@@ -1522,6 +1539,7 @@ export interface NativeButtonProps extends NativeEventAttributes {
|
|
|
1522
1539
|
}
|
|
1523
1540
|
|
|
1524
1541
|
export interface NativeVirtualListProps extends NativeEventAttributes {
|
|
1542
|
+
onScroll?: (event: Event) => void
|
|
1525
1543
|
id?: string
|
|
1526
1544
|
class?: ClassValue
|
|
1527
1545
|
style?: Style
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geastack/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.26",
|
|
4
4
|
"description": "GeaStack app API, reactivity headers, runtime sources, and type declarations.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
"@babel/parser": "^7.23.0",
|
|
61
61
|
"@babel/traverse": "^7.23.0",
|
|
62
62
|
"@babel/types": "^7.23.0",
|
|
63
|
-
"@geajs/core": "1.4.
|
|
64
|
-
"@geajs/vite-plugin": "1.4.
|
|
63
|
+
"@geajs/core": "1.4.3",
|
|
64
|
+
"@geajs/vite-plugin": "1.4.3",
|
|
65
65
|
"@geastack/compiler": "^1.0.15",
|
|
66
|
-
"@geastack/geatsc-plugin-gea": "^0.1.
|
|
66
|
+
"@geastack/geatsc-plugin-gea": "^0.1.7",
|
|
67
67
|
"opentype.js": "^2.0.0",
|
|
68
68
|
"vite": "^8.0.0"
|
|
69
69
|
}
|
package/runtime.cpp
CHANGED
|
@@ -35,6 +35,13 @@
|
|
|
35
35
|
#define GEA_EMBEDDED_WIFI_EARLY_CONNECT 0
|
|
36
36
|
#endif
|
|
37
37
|
|
|
38
|
+
// UI/audio applications can keep touch event-driven rather than spending CPU
|
|
39
|
+
// on back-to-back no-op frames between samples. Touch events still request an
|
|
40
|
+
// immediate frame; animations continue on the configured frame timer.
|
|
41
|
+
#ifndef GEA_EMBEDDED_CONTINUOUS_TOUCH_FRAMES
|
|
42
|
+
#define GEA_EMBEDDED_CONTINUOUS_TOUCH_FRAMES 1
|
|
43
|
+
#endif
|
|
44
|
+
|
|
38
45
|
#include "css/declarative.h"
|
|
39
46
|
#include "css/engine.h"
|
|
40
47
|
#include "ui/style.h"
|
|
@@ -190,6 +197,7 @@ void dispatch_event(const events::Event &event, const RuntimeOptions &options)
|
|
|
190
197
|
for (;;) {
|
|
191
198
|
const bool catchUp = services::FrameScheduler::takeCatchUpRequest();
|
|
192
199
|
const bool activeDrag =
|
|
200
|
+
GEA_EMBEDDED_CONTINUOUS_TOUCH_FRAMES &&
|
|
193
201
|
events::TouchRuntime::gestureActiveWithin(services::FrameScheduler::nowMs(), 50);
|
|
194
202
|
// TE single-clock: never run a frame back-to-back here — the panel TE posts the
|
|
195
203
|
// next frame exactly one VBlank later, which is the whole point. Back-to-back
|
|
@@ -1491,6 +1491,7 @@ function parseStaticSimpleSelectorSpec(rawSimple) {
|
|
|
1491
1491
|
wantsRoot: false,
|
|
1492
1492
|
wantsFirstChild: false,
|
|
1493
1493
|
wantsLastChild: false,
|
|
1494
|
+
wantsHover: false,
|
|
1494
1495
|
}
|
|
1495
1496
|
let i = 0
|
|
1496
1497
|
if (simple[i] !== '.' && simple[i] !== '#' && simple[i] !== ':') {
|
|
@@ -1514,13 +1515,14 @@ function parseStaticSimpleSelectorSpec(rawSimple) {
|
|
|
1514
1515
|
if (token === 'root') spec.wantsRoot = true
|
|
1515
1516
|
else if (token === 'first-child') spec.wantsFirstChild = true
|
|
1516
1517
|
else if (token === 'last-child') spec.wantsLastChild = true
|
|
1518
|
+
else if (token === 'hover') spec.wantsHover = true
|
|
1517
1519
|
else return null
|
|
1518
1520
|
} else {
|
|
1519
1521
|
return null
|
|
1520
1522
|
}
|
|
1521
1523
|
}
|
|
1522
1524
|
if (!spec.tag && !spec.id && spec.classes.length === 0 &&
|
|
1523
|
-
!spec.wantsRoot && !spec.wantsFirstChild && !spec.wantsLastChild) {
|
|
1525
|
+
!spec.wantsRoot && !spec.wantsFirstChild && !spec.wantsLastChild && !spec.wantsHover) {
|
|
1524
1526
|
return null
|
|
1525
1527
|
}
|
|
1526
1528
|
return spec
|
|
@@ -1555,7 +1557,7 @@ function staticSimpleSelectorSpecCode(simple) {
|
|
|
1555
1557
|
const tag = simple.tag ? JSON.stringify(simple.tag) : 'nullptr'
|
|
1556
1558
|
const id = simple.id ? JSON.stringify(simple.id) : 'nullptr'
|
|
1557
1559
|
const classes = simple.classes.map((className) => JSON.stringify(className)).join(', ')
|
|
1558
|
-
return `{${tag}, ${id}, {${classes}}, ${simple.wantsRoot ? 'true' : 'false'}, ${simple.wantsFirstChild ? 'true' : 'false'}, ${simple.wantsLastChild ? 'true' : 'false'}}`
|
|
1560
|
+
return `{${tag}, ${id}, {${classes}}, ${simple.wantsRoot ? 'true' : 'false'}, ${simple.wantsFirstChild ? 'true' : 'false'}, ${simple.wantsLastChild ? 'true' : 'false'}, ${simple.wantsHover ? 'true' : 'false'}}`
|
|
1559
1561
|
}
|
|
1560
1562
|
|
|
1561
1563
|
function staticSelectorPartSpecCode(part) {
|
|
@@ -1872,8 +1874,8 @@ function parseStaticCssLengthSpec(rawValue) {
|
|
|
1872
1874
|
|
|
1873
1875
|
function cssAlignKeywordValue(value) {
|
|
1874
1876
|
const align = new Map([
|
|
1875
|
-
['flex-start',
|
|
1876
|
-
['start',
|
|
1877
|
+
['flex-start', 6],
|
|
1878
|
+
['start', 6],
|
|
1877
1879
|
['stretch', 0],
|
|
1878
1880
|
['normal', 0],
|
|
1879
1881
|
['center', 1],
|
|
@@ -1939,8 +1941,9 @@ function cssStaticColorTarget(property) {
|
|
|
1939
1941
|
case 'color':
|
|
1940
1942
|
return 'Color'
|
|
1941
1943
|
case 'background':
|
|
1942
|
-
case 'background-color':
|
|
1943
1944
|
return 'Background'
|
|
1945
|
+
case 'background-color':
|
|
1946
|
+
return 'BackgroundColor'
|
|
1944
1947
|
case 'active-background':
|
|
1945
1948
|
case 'active-background-color':
|
|
1946
1949
|
return 'ActiveBackground'
|
|
@@ -1997,9 +2000,6 @@ function parseStaticCssColorRef(rawValue) {
|
|
|
1997
2000
|
function cssIgnoredProperty(property) {
|
|
1998
2001
|
return new Set([
|
|
1999
2002
|
'color-scheme',
|
|
2000
|
-
'background-position',
|
|
2001
|
-
'box-sizing',
|
|
2002
|
-
'font',
|
|
2003
2003
|
'grid-column',
|
|
2004
2004
|
'isolation',
|
|
2005
2005
|
'letter-spacing',
|
|
@@ -2008,7 +2008,6 @@ function cssIgnoredProperty(property) {
|
|
|
2008
2008
|
'scroll-snap-type',
|
|
2009
2009
|
'scrollbar-width',
|
|
2010
2010
|
'text-shadow',
|
|
2011
|
-
'transform-style',
|
|
2012
2011
|
'transition',
|
|
2013
2012
|
'cursor',
|
|
2014
2013
|
'-webkit-tap-highlight-color',
|
|
@@ -2047,6 +2046,10 @@ function cssStaticPropertyValue(property, rawValue) {
|
|
|
2047
2046
|
const values = new Map([['block', 0], ['none', 1], ['grid', 2], ['inline-grid', 2], ['flex', 3], ['inline-flex', 3]])
|
|
2048
2047
|
return values.has(value) ? direct('Display', values.get(value)) : null
|
|
2049
2048
|
}
|
|
2049
|
+
case 'box-sizing':
|
|
2050
|
+
if (value === 'content-box') return direct('BoxSizing', 0)
|
|
2051
|
+
if (value === 'border-box') return direct('BoxSizing', 1)
|
|
2052
|
+
return null
|
|
2050
2053
|
case 'flex-direction':
|
|
2051
2054
|
if (value === 'column') return direct('FlexDirection', 0)
|
|
2052
2055
|
if (value === 'row') return direct('FlexDirection', 1)
|
|
@@ -2134,10 +2137,6 @@ function cssStaticPropertyValue(property, rawValue) {
|
|
|
2134
2137
|
if (lower === 'none') return direct('ImageFit', 3)
|
|
2135
2138
|
if (lower === 'scale-down') return direct('ImageFit', 4)
|
|
2136
2139
|
return null
|
|
2137
|
-
case 'rotate': {
|
|
2138
|
-
const angle = parseStaticAngleTenths(value)
|
|
2139
|
-
return angle === null ? null : direct('TransformRotate', angle)
|
|
2140
|
-
}
|
|
2141
2140
|
case 'text-align':
|
|
2142
2141
|
if (value === 'left' || value === 'start') return direct('TextAlign', 0)
|
|
2143
2142
|
if (value === 'center') return direct('TextAlign', 1)
|
|
@@ -2208,11 +2207,8 @@ function cssStaticPropertyValues(property, rawValue) {
|
|
|
2208
2207
|
}
|
|
2209
2208
|
const boxLength = directLengthValue(length)
|
|
2210
2209
|
if (boxLength !== null) {
|
|
2211
|
-
|
|
2212
|
-
if (
|
|
2213
|
-
if (property === 'border-right') return [direct('BorderRightWidth', boxLength)]
|
|
2214
|
-
if (property === 'border-bottom') return [direct('BorderBottomWidth', boxLength)]
|
|
2215
|
-
if (property === 'border-left') return [direct('BorderLeftWidth', boxLength)]
|
|
2210
|
+
const border = {border:'Border','border-top':'BorderTop','border-right':'BorderRight','border-bottom':'BorderBottom','border-left':'BorderLeft'}[property]
|
|
2211
|
+
if (border) return [direct(`${border}Width`, boxLength), direct(`${border}Relief`, 0), direct(`${border}ColorCurrent`, 1)]
|
|
2216
2212
|
if (property === 'margin') {
|
|
2217
2213
|
return [
|
|
2218
2214
|
direct('MarginTop', boxLength),
|
|
@@ -2250,14 +2246,37 @@ function cssStaticPropertyValues(property, rawValue) {
|
|
|
2250
2246
|
}
|
|
2251
2247
|
}
|
|
2252
2248
|
|
|
2253
|
-
if (property === '
|
|
2254
|
-
const
|
|
2255
|
-
if (
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2249
|
+
if (property === 'rotate') {
|
|
2250
|
+
const parts = value.toLowerCase().split(/\s+/)
|
|
2251
|
+
if (parts.length > 1 && (/(deg|rad|turn|grad)$/.test(parts[0]) ||
|
|
2252
|
+
(parts.length === 2 && ['x', 'y', 'z'].includes(parts[1])))) parts.push(parts.shift())
|
|
2253
|
+
const none = value.toLowerCase() === 'none'
|
|
2254
|
+
const angle = none ? 0 : parseStaticAngleTenths(parts.at(-1))
|
|
2255
|
+
if (angle === null || ![1, 2, 4].includes(parts.length)) return []
|
|
2256
|
+
if (!none && !/(deg|rad|turn)$/i.test(parts.at(-1)) && Number(parts.at(-1)) !== 0) return []
|
|
2257
|
+
let axes = [0, 0, 1000000]
|
|
2258
|
+
if (parts.length === 2) {
|
|
2259
|
+
const axis = ['x', 'y', 'z'].indexOf(parts[0])
|
|
2260
|
+
if (axis < 0) return []
|
|
2261
|
+
axes = [0, 0, 0]; axes[axis] = 1000000
|
|
2262
|
+
} else if (parts.length === 4) {
|
|
2263
|
+
const vector = parts.slice(0, 3).map(Number)
|
|
2264
|
+
if (!vector.every(Number.isFinite)) return []
|
|
2265
|
+
const magnitude = Math.max(...vector.map(Math.abs))
|
|
2266
|
+
axes = magnitude ? vector.map(v => roundCssNumber(v / magnitude * 1000000)) : [0, 0, 0]
|
|
2260
2267
|
}
|
|
2268
|
+
return [direct('RotatePresent', none ? 0 : 1), direct('RotateAngle', axes.some(Boolean) ? angle : 0),
|
|
2269
|
+
direct('RotateAxisX', axes[0]), direct('RotateAxisY', axes[1]), direct('RotateAxisZ', axes[2])]
|
|
2270
|
+
}
|
|
2271
|
+
if (property === 'scale') {
|
|
2272
|
+
const none = value.toLowerCase() === 'none'
|
|
2273
|
+
const parts = none ? ['1'] : value.split(/\s+/)
|
|
2274
|
+
if (parts.length < 1 || parts.length > 3) return []
|
|
2275
|
+
const factors = parts.map(v => v.endsWith('%') ? Number(v.slice(0, -1)) / 100 : Number(v))
|
|
2276
|
+
if (!factors.every(Number.isFinite)) return []
|
|
2277
|
+
const scales = factors.map(v => roundCssNumber(Math.max(-32768, Math.min(32767, v * 1000))))
|
|
2278
|
+
return [direct('ScalePresent', none ? 0 : 1), direct('ScaleX', scales[0]),
|
|
2279
|
+
direct('ScaleY', scales[1] ?? scales[0]), direct('ScaleZ', scales[2] ?? 1000)]
|
|
2261
2280
|
}
|
|
2262
2281
|
|
|
2263
2282
|
return []
|
|
@@ -2311,27 +2330,15 @@ function cssStaticFlexValue(property, rawValue) {
|
|
|
2311
2330
|
const setup = []
|
|
2312
2331
|
const words = splitCssWords(rawValue.trim())
|
|
2313
2332
|
if (words.length === 0) return null
|
|
2333
|
+
// The compact static API has no shrink field. Preserve declarations it
|
|
2334
|
+
// cannot represent through the full compiler, including keyword semantics.
|
|
2335
|
+
if (words.some(word => /^(none|auto|content|max-content|min-content|fit-content)$/i.test(word))) return null
|
|
2314
2336
|
for (const token of words) {
|
|
2315
|
-
const lower = token.toLowerCase()
|
|
2316
|
-
if (lower === 'none') {
|
|
2317
|
-
grow = 0
|
|
2318
|
-
hasBasis = false
|
|
2319
|
-
continue
|
|
2320
|
-
}
|
|
2321
|
-
if (
|
|
2322
|
-
lower === 'auto' ||
|
|
2323
|
-
lower === 'content' ||
|
|
2324
|
-
lower === 'max-content' ||
|
|
2325
|
-
lower === 'min-content' ||
|
|
2326
|
-
lower === 'fit-content' ||
|
|
2327
|
-
lower.includes('%')
|
|
2328
|
-
) {
|
|
2329
|
-
hasBasis = false
|
|
2330
|
-
continue
|
|
2331
|
-
}
|
|
2332
2337
|
const number = Number(token)
|
|
2333
2338
|
if (Number.isFinite(number) && token.match(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/)) {
|
|
2339
|
+
if (number < 0 || numberIndex > 1) return null
|
|
2334
2340
|
if (numberIndex === 0) grow = roundCssNumber(number)
|
|
2341
|
+
else if (number !== 1) return null
|
|
2335
2342
|
numberIndex++
|
|
2336
2343
|
continue
|
|
2337
2344
|
}
|
|
@@ -2399,6 +2406,7 @@ function cssStaticBorderRadiusValue(property, rawValue) {
|
|
|
2399
2406
|
|
|
2400
2407
|
function cssStaticBorderValue(property, rawValue) {
|
|
2401
2408
|
if (property !== 'border') return null
|
|
2409
|
+
if (/\b(?:groove|ridge|inset|outset)\b/i.test(rawValue)) return null
|
|
2402
2410
|
const parts = splitCssWords(rawValue.trim())
|
|
2403
2411
|
if (parts.length === 0) return null
|
|
2404
2412
|
const width = parseStaticCssLengthSpec(parts[0])
|
|
@@ -2414,6 +2422,8 @@ function cssStaticBorderValue(property, rawValue) {
|
|
|
2414
2422
|
}
|
|
2415
2423
|
|
|
2416
2424
|
function cssStaticBorderShorthandValue(property, rawValue) {
|
|
2425
|
+
// The compact width/color API cannot carry a shaded border style.
|
|
2426
|
+
if (/\b(?:groove|ridge|inset|outset)\b/i.test(rawValue)) return null
|
|
2417
2427
|
const targets = {
|
|
2418
2428
|
border: { width: 'BorderWidth', color: 'Border', colorProperty: 'border-color', side: false },
|
|
2419
2429
|
'border-top': { width: 'BorderTopWidth', color: 'BorderTop', colorProperty: 'border-top-color', side: true },
|
|
@@ -2441,7 +2451,8 @@ function cssStaticBorderShorthandValue(property, rawValue) {
|
|
|
2441
2451
|
}
|
|
2442
2452
|
}
|
|
2443
2453
|
if (!targets.side && color && !colorVar) return null
|
|
2444
|
-
return { setup: width.setup, widthTarget: targets.width,
|
|
2454
|
+
return { setup: width.setup, widthTarget: targets.width, reliefTarget: targets.width.replace('Width', 'Relief'),
|
|
2455
|
+
currentColorTarget: `${targets.color}ColorCurrent`, width: width.spec, color, colorVar }
|
|
2445
2456
|
}
|
|
2446
2457
|
|
|
2447
2458
|
function staticColorCode(color) {
|
|
@@ -2781,6 +2792,9 @@ function cssStaticBackgroundValue(property, rawValue) {
|
|
|
2781
2792
|
if (cssHasDynamicValue(rawValue)) return null
|
|
2782
2793
|
const layers = splitTopLevelCss(rawValue, ',')
|
|
2783
2794
|
if (layers.length === 0) return null
|
|
2795
|
+
// The gradient registration API has no base-color field. Keep combined
|
|
2796
|
+
// color/image shorthands on the complete native declaration parser.
|
|
2797
|
+
if (layers.some(layer => splitCssWords(layer).some(word => parseStaticCssColor(word) || /^(?:none|border-box|padding-box|content-box)$/i.test(word)))) return null
|
|
2784
2798
|
|
|
2785
2799
|
const out = {
|
|
2786
2800
|
setup: [],
|
|
@@ -2816,6 +2830,7 @@ function cssStaticBackgroundValue(property, rawValue) {
|
|
|
2816
2830
|
}
|
|
2817
2831
|
|
|
2818
2832
|
if (!out.gradient) return null
|
|
2833
|
+
if (layers.length !== 1 + Number(out.hasOverlayGradient) + Number(Boolean(out.radialGradient?.enabled)) + Number(Boolean(out.gridX)) + Number(Boolean(out.gridY))) return null
|
|
2819
2834
|
if (out.gridX && out.gridY && !staticColorEquals(out.gridX.color, out.gridY.color) && out.gridOrder.join('') !== 'xy') return null
|
|
2820
2835
|
return out
|
|
2821
2836
|
}
|
|
@@ -2837,6 +2852,9 @@ function cssStaticBackgroundFullValue(property, rawValue) {
|
|
|
2837
2852
|
return null
|
|
2838
2853
|
const layers = splitTopLevelCss(rawValue, ',')
|
|
2839
2854
|
if (layers.length === 0) return null
|
|
2855
|
+
// The gradient registration API has no base-color field. Keep combined
|
|
2856
|
+
// color/image shorthands on the complete native declaration parser.
|
|
2857
|
+
if (layers.some(layer => splitCssWords(layer).some(word => parseStaticCssColor(word) || /^(?:none|border-box|padding-box|content-box)$/i.test(word)))) return null
|
|
2840
2858
|
|
|
2841
2859
|
const out = {
|
|
2842
2860
|
setup: [],
|
|
@@ -2883,6 +2901,7 @@ function cssStaticBackgroundFullValue(property, rawValue) {
|
|
|
2883
2901
|
}
|
|
2884
2902
|
|
|
2885
2903
|
if (!out.gradient) return null
|
|
2904
|
+
if (layers.length !== 1 + Number(out.hasOverlayGradient) + Number(Boolean(out.radialGradient?.enabled)) + Number(Boolean(out.gridX)) + Number(Boolean(out.gridY))) return null
|
|
2886
2905
|
if (out.gridX && out.gridY && !staticColorEquals(out.gridX.color, out.gridY.color) && out.gridOrder.join('') !== 'xy') return null
|
|
2887
2906
|
return out.needsFullApi ? out : null
|
|
2888
2907
|
}
|
|
@@ -2891,12 +2910,15 @@ function cssStaticBackgroundSizeValue(property, rawValue) {
|
|
|
2891
2910
|
if (property !== 'background-size') return null
|
|
2892
2911
|
if (cssHasDynamicValue(rawValue)) return null
|
|
2893
2912
|
const layers = splitTopLevelCss(rawValue, ',')
|
|
2894
|
-
if (layers.length
|
|
2913
|
+
if (layers.length !== 1) return null
|
|
2895
2914
|
const parts = splitCssWords(layers[0])
|
|
2896
|
-
if (parts.length === 0) return null
|
|
2897
|
-
const
|
|
2915
|
+
if (parts.length === 0 || parts.length > 2) return null
|
|
2916
|
+
const parseSize = value => value.toLowerCase() === 'auto'
|
|
2917
|
+
? { setup: [], spec: { unit: 'Auto', value: '0' } }
|
|
2918
|
+
: parseStaticCssLengthSpec(value)
|
|
2919
|
+
const x = parseSize(parts[0])
|
|
2898
2920
|
if (!x) return null
|
|
2899
|
-
const y = parts.length > 1 ?
|
|
2921
|
+
const y = parseSize(parts.length > 1 ? parts[1] : 'auto')
|
|
2900
2922
|
if (!y) return null
|
|
2901
2923
|
return { setup: [...x.setup, ...(y === x ? [] : y.setup)], stepX: x.spec, stepY: y.spec }
|
|
2902
2924
|
}
|
|
@@ -3192,6 +3214,7 @@ const staticTransformFlags = {
|
|
|
3192
3214
|
translateZ: 1 << 5,
|
|
3193
3215
|
scaleX: 1 << 8,
|
|
3194
3216
|
scaleY: 1 << 9,
|
|
3217
|
+
scaleZ: 1 << 13,
|
|
3195
3218
|
}
|
|
3196
3219
|
|
|
3197
3220
|
function parseStaticAngleTenths(rawValue) {
|
|
@@ -3212,7 +3235,14 @@ function parseStaticScalePermille(rawValue) {
|
|
|
3212
3235
|
return roundCssNumber(value * 1000)
|
|
3213
3236
|
}
|
|
3214
3237
|
|
|
3238
|
+
function multiplyStaticScalePermille(left, right) {
|
|
3239
|
+
return clampInt16(roundCssNumber((left * right) / 1000))
|
|
3240
|
+
}
|
|
3241
|
+
|
|
3215
3242
|
function parseStaticTransformValue(rawValue) {
|
|
3243
|
+
// Multiple rotation functions need ordered composition. Use the shared C++
|
|
3244
|
+
// CSS compiler rather than independently decomposing a matrix in JS.
|
|
3245
|
+
if ((rawValue.match(/rotate(?:x|y|z|3d)?\s*\(/gi) || []).length > 1) return null
|
|
3216
3246
|
const value = rawValue.trim()
|
|
3217
3247
|
const out = {
|
|
3218
3248
|
setup: [],
|
|
@@ -3225,6 +3255,7 @@ function parseStaticTransformValue(rawValue) {
|
|
|
3225
3255
|
translateZ: zeroStaticLengthSpec(),
|
|
3226
3256
|
scaleX: 1000,
|
|
3227
3257
|
scaleY: 1000,
|
|
3258
|
+
scaleZ: 1000,
|
|
3228
3259
|
}
|
|
3229
3260
|
let sawTransform = false
|
|
3230
3261
|
let i = 0
|
|
@@ -3247,6 +3278,9 @@ function parseStaticTransformValue(rawValue) {
|
|
|
3247
3278
|
if (depth !== 0) return null
|
|
3248
3279
|
const arg = value.slice(argStart, i - 1)
|
|
3249
3280
|
const args = splitTopLevelCss(arg, ',')
|
|
3281
|
+
const axes = name === 'translatex' ? 1 : name === 'translatey' ? 2 : name === 'translatez' ? 4 :
|
|
3282
|
+
(name === 'translate' || name === 'translate3d') ? (1 << Math.min(3, args.length)) - 1 : 0
|
|
3283
|
+
out.flags = (out.flags & ~(axes << 10)) | ((out.flags & 7) ? 0 : (axes << 10))
|
|
3250
3284
|
sawTransform = true
|
|
3251
3285
|
|
|
3252
3286
|
const setLength = (field, flag, raw) => {
|
|
@@ -3288,19 +3322,34 @@ function parseStaticTransformValue(rawValue) {
|
|
|
3288
3322
|
const sx = parseStaticScalePermille(args[0] ?? arg)
|
|
3289
3323
|
const sy = parseStaticScalePermille(args[1] ?? args[0] ?? arg)
|
|
3290
3324
|
if (sx === null || sy === null) return null
|
|
3291
|
-
out.scaleX = sx
|
|
3292
|
-
out.scaleY = sy
|
|
3325
|
+
out.scaleX = multiplyStaticScalePermille(out.scaleX, sx)
|
|
3326
|
+
out.scaleY = multiplyStaticScalePermille(out.scaleY, sy)
|
|
3293
3327
|
out.flags |= staticTransformFlags.scaleX | staticTransformFlags.scaleY
|
|
3328
|
+
} else if (name === 'scale3d') {
|
|
3329
|
+
if (args.length !== 3) return null
|
|
3330
|
+
const sx = parseStaticScalePermille(args[0])
|
|
3331
|
+
const sy = parseStaticScalePermille(args[1])
|
|
3332
|
+
const sz = parseStaticScalePermille(args[2])
|
|
3333
|
+
if (sx === null || sy === null || sz === null) return null
|
|
3334
|
+
out.scaleX = multiplyStaticScalePermille(out.scaleX, sx)
|
|
3335
|
+
out.scaleY = multiplyStaticScalePermille(out.scaleY, sy)
|
|
3336
|
+
out.scaleZ = multiplyStaticScalePermille(out.scaleZ, sz)
|
|
3337
|
+
out.flags |= staticTransformFlags.scaleX | staticTransformFlags.scaleY | staticTransformFlags.scaleZ
|
|
3294
3338
|
} else if (name === 'scalex') {
|
|
3295
3339
|
const scale = parseStaticScalePermille(arg)
|
|
3296
3340
|
if (scale === null) return null
|
|
3297
|
-
out.scaleX = scale
|
|
3341
|
+
out.scaleX = multiplyStaticScalePermille(out.scaleX, scale)
|
|
3298
3342
|
out.flags |= staticTransformFlags.scaleX
|
|
3299
3343
|
} else if (name === 'scaley') {
|
|
3300
3344
|
const scale = parseStaticScalePermille(arg)
|
|
3301
3345
|
if (scale === null) return null
|
|
3302
|
-
out.scaleY = scale
|
|
3346
|
+
out.scaleY = multiplyStaticScalePermille(out.scaleY, scale)
|
|
3303
3347
|
out.flags |= staticTransformFlags.scaleY
|
|
3348
|
+
} else if (name === 'scalez') {
|
|
3349
|
+
const scale = parseStaticScalePermille(arg)
|
|
3350
|
+
if (scale === null) return null
|
|
3351
|
+
out.scaleZ = multiplyStaticScalePermille(out.scaleZ, scale)
|
|
3352
|
+
out.flags |= staticTransformFlags.scaleZ
|
|
3304
3353
|
} else {
|
|
3305
3354
|
return null
|
|
3306
3355
|
}
|
|
@@ -3313,17 +3362,29 @@ function cssStaticTransformValue(property, rawValue) {
|
|
|
3313
3362
|
return parseStaticTransformValue(rawValue)
|
|
3314
3363
|
}
|
|
3315
3364
|
|
|
3316
|
-
function staticTransformArgs(transform) {
|
|
3317
|
-
|
|
3365
|
+
function staticTransformArgs(transform, mediaArg = null) {
|
|
3366
|
+
const fields = `${transform.flags}, ${transform.rotateX}, ${transform.rotateY}, ${transform.rotateZ}, ${staticLengthSpecCode(transform.translateX)}, ${staticLengthSpecCode(transform.translateY)}, ${staticLengthSpecCode(transform.translateZ)}, ${transform.scaleX}, ${transform.scaleY}`
|
|
3367
|
+
if (mediaArg === null) return `${fields}, ${transform.scaleZ}`
|
|
3368
|
+
return `${fields}${mediaArg || ', nullptr'}, ${transform.scaleZ}`
|
|
3318
3369
|
}
|
|
3319
3370
|
|
|
3320
3371
|
const staticAnimatableLengthTargets = new Set(['Width', 'Height', 'Top', 'Left'])
|
|
3321
|
-
const staticAnimatableColorTargets = new Set(['Color', 'Background'])
|
|
3372
|
+
const staticAnimatableColorTargets = new Set(['Color', 'Background', 'BackgroundColor'])
|
|
3322
3373
|
const staticAnimatableDirectProperties = new Set([
|
|
3323
3374
|
'gea::embedded::ui::Property::Opacity',
|
|
3375
|
+
'gea::embedded::ui::Property::RotatePresent',
|
|
3376
|
+
'gea::embedded::ui::Property::RotateAngle',
|
|
3377
|
+
'gea::embedded::ui::Property::RotateAxisX',
|
|
3378
|
+
'gea::embedded::ui::Property::RotateAxisY',
|
|
3379
|
+
'gea::embedded::ui::Property::RotateAxisZ',
|
|
3380
|
+
'gea::embedded::ui::Property::ScalePresent',
|
|
3381
|
+
'gea::embedded::ui::Property::ScaleX',
|
|
3382
|
+
'gea::embedded::ui::Property::ScaleY',
|
|
3383
|
+
'gea::embedded::ui::Property::ScaleZ',
|
|
3324
3384
|
'gea::embedded::ui::Property::TransformRotate',
|
|
3325
3385
|
'gea::embedded::ui::Property::TransformScaleX',
|
|
3326
3386
|
'gea::embedded::ui::Property::TransformScaleY',
|
|
3387
|
+
'gea::embedded::ui::Property::TransformScaleZ',
|
|
3327
3388
|
])
|
|
3328
3389
|
|
|
3329
3390
|
function cssStaticFilterBlurValue(property, rawValue) {
|
|
@@ -3437,12 +3498,14 @@ function emitCssRuleRegistrations(kind, selector, name, value, mediaCondition) {
|
|
|
3437
3498
|
`__gea_stylesheet.registerStaticPropertyRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, ${direct.property}, ${direct.value}${mediaArg});`,
|
|
3438
3499
|
]
|
|
3439
3500
|
}
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3501
|
+
// Each native compiled property group has four slots.
|
|
3502
|
+
const registrations = []
|
|
3503
|
+
for (let i = 0; i < directProperties.length; i += 4) {
|
|
3504
|
+
const entries = directProperties.slice(i, i + 4)
|
|
3505
|
+
.map(direct => `{${direct.property}, ${direct.value}}`).join(', ')
|
|
3506
|
+
registrations.push(`__gea_stylesheet.registerStaticPropertyGroupRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, {${entries}}${mediaArg});`)
|
|
3507
|
+
}
|
|
3508
|
+
return registrations
|
|
3446
3509
|
}
|
|
3447
3510
|
const flex = cssStaticFlexValue(name, value)
|
|
3448
3511
|
if (flex) {
|
|
@@ -3478,6 +3541,7 @@ function emitCssRuleRegistrations(kind, selector, name, value, mediaCondition) {
|
|
|
3478
3541
|
const calls = [
|
|
3479
3542
|
...borderShorthand.setup,
|
|
3480
3543
|
`__gea_stylesheet.registerStaticLengthSpecRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, gea::embedded::ui::StaticStyleLengthProperty::${borderShorthand.widthTarget}, ${staticLengthSpecCode(borderShorthand.width)}${mediaArg});`,
|
|
3544
|
+
`__gea_stylesheet.registerStaticPropertyRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, gea::embedded::ui::Property::${borderShorthand.reliefTarget}, 0${mediaArg});`,
|
|
3481
3545
|
]
|
|
3482
3546
|
if (borderShorthand.colorVar) {
|
|
3483
3547
|
const colorVar = borderShorthand.colorVar
|
|
@@ -3485,6 +3549,8 @@ function emitCssRuleRegistrations(kind, selector, name, value, mediaCondition) {
|
|
|
3485
3549
|
} else if (borderShorthand.color) {
|
|
3486
3550
|
const color = borderShorthand.color
|
|
3487
3551
|
calls.push(`__gea_stylesheet.registerStaticColorRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, gea::embedded::ui::StaticStyleColorProperty::${color.target}, ${color.color.r}, ${color.color.g}, ${color.color.b}, ${color.color.a}${mediaArg});`)
|
|
3552
|
+
} else {
|
|
3553
|
+
calls.push(`__gea_stylesheet.registerStaticPropertyRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, gea::embedded::ui::Property::${borderShorthand.currentColorTarget}, 1${mediaArg});`)
|
|
3488
3554
|
}
|
|
3489
3555
|
return calls
|
|
3490
3556
|
}
|
|
@@ -3519,14 +3585,14 @@ function emitCssRuleRegistrations(kind, selector, name, value, mediaCondition) {
|
|
|
3519
3585
|
if (fullBackground) {
|
|
3520
3586
|
return [
|
|
3521
3587
|
...fullBackground.setup,
|
|
3522
|
-
`__gea_stylesheet.registerStaticBackgroundFullRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, ${staticLinearGradientRefCode(fullBackground.gradient)}, ${staticLinearGradientRefCode(fullBackground.overlayGradient)}, ${fullBackground.hasOverlayGradient ? 'true' : 'false'}, ${staticRadialGradientRefCode(fullBackground.radialGradient)}, ${staticGridLineCode(fullBackground.gridX)}, ${staticGridLineCode(fullBackground.gridY)}${mediaArg});`,
|
|
3588
|
+
`__gea_stylesheet.registerStaticBackgroundFullRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, ${staticLinearGradientRefCode(fullBackground.gradient)}, ${staticLinearGradientRefCode(fullBackground.overlayGradient)}, ${fullBackground.hasOverlayGradient ? 'true' : 'false'}, ${staticRadialGradientRefCode(fullBackground.radialGradient)}, ${staticGridLineCode(fullBackground.gridX)}, ${staticGridLineCode(fullBackground.gridY)}${mediaArg || ", nullptr"}, ${name === "background-image" ? "true" : "false"});`,
|
|
3523
3589
|
]
|
|
3524
3590
|
}
|
|
3525
3591
|
const background = cssStaticBackgroundValue(name, value)
|
|
3526
3592
|
if (background) {
|
|
3527
3593
|
return [
|
|
3528
3594
|
...background.setup,
|
|
3529
|
-
`__gea_stylesheet.registerStaticBackgroundRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, ${staticLinearGradientCode(background.gradient)}, ${staticLinearGradientCode(background.overlayGradient)}, ${background.hasOverlayGradient ? 'true' : 'false'}, ${staticGridLineCode(background.gridX)}, ${staticGridLineCode(background.gridY)}${mediaArg});`,
|
|
3595
|
+
`__gea_stylesheet.registerStaticBackgroundRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, ${staticLinearGradientCode(background.gradient)}, ${staticLinearGradientCode(background.overlayGradient)}, ${background.hasOverlayGradient ? 'true' : 'false'}, ${staticGridLineCode(background.gridX)}, ${staticGridLineCode(background.gridY)}${mediaArg || ", nullptr"}, ${name === "background-image" ? "true" : "false"});`,
|
|
3530
3596
|
]
|
|
3531
3597
|
}
|
|
3532
3598
|
const backgroundSize = cssStaticBackgroundSizeValue(name, value)
|
|
@@ -3591,7 +3657,7 @@ function emitCssRuleRegistrations(kind, selector, name, value, mediaCondition) {
|
|
|
3591
3657
|
if (transform) {
|
|
3592
3658
|
return [
|
|
3593
3659
|
...transform.setup,
|
|
3594
|
-
`__gea_stylesheet.registerStaticTransformRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, ${staticTransformArgs(transform)}
|
|
3660
|
+
`__gea_stylesheet.registerStaticTransformRule(${staticSelectorKind(kind)}, ${JSON.stringify(selector)}, ${staticTransformArgs(transform, mediaArg)});`,
|
|
3595
3661
|
]
|
|
3596
3662
|
}
|
|
3597
3663
|
}
|
|
@@ -3810,6 +3876,9 @@ function staticCssTapeLengthSpecParts(code) {
|
|
|
3810
3876
|
if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) return null
|
|
3811
3877
|
const parts = splitTopLevelCppArgs(trimmed.slice(1, -1))
|
|
3812
3878
|
if (parts.length !== 2) return null
|
|
3879
|
+
// The tape is constexpr: a length expression's value is the id its
|
|
3880
|
+
// registration returned at run time, so that rule stays a plain call.
|
|
3881
|
+
if (!/^[-+]?(\d+\.?\d*|\.\d+)(e[-+]?\d+)?f?$/i.test(parts[1].trim())) return null
|
|
3813
3882
|
return { unit: parts[0], value: parts[1] }
|
|
3814
3883
|
}
|
|
3815
3884
|
|
|
@@ -3989,31 +4058,38 @@ auto __gea_css_tape_selector_kind = [](std::uint8_t kind) {
|
|
|
3989
4058
|
auto __gea_css_tape_length = [](std::uint8_t unit, float value) {
|
|
3990
4059
|
\treturn gea::embedded::ui::StaticStyleLengthSpec{static_cast<gea::embedded::ui::StaticStyleLengthUnit>(unit), value};
|
|
3991
4060
|
};
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
\tstd::
|
|
3997
|
-
\
|
|
3998
|
-
\
|
|
3999
|
-
\
|
|
4000
|
-
\
|
|
4001
|
-
\
|
|
4002
|
-
\
|
|
4003
|
-
\
|
|
4004
|
-
\
|
|
4005
|
-
\
|
|
4006
|
-
\
|
|
4007
|
-
\
|
|
4008
|
-
\
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
\
|
|
4012
|
-
\
|
|
4013
|
-
\
|
|
4014
|
-
\
|
|
4015
|
-
\
|
|
4016
|
-
\
|
|
4061
|
+
// Each tape's lists are static constexpr arrays the call points into: an
|
|
4062
|
+
// initializer_list argument is a temporary array, which the compiler builds on
|
|
4063
|
+
// the stack by copying it out of read-only data at every call.
|
|
4064
|
+
struct __GeaStaticCssTape {
|
|
4065
|
+
\tstd::size_t orderCount;
|
|
4066
|
+
\tconst __GeaStaticCssTapeKind *order;
|
|
4067
|
+
\tconst __GeaStaticCssPropertyOp *propertyOps;
|
|
4068
|
+
\tconst __GeaStaticCssLengthOp *lengthOps;
|
|
4069
|
+
\tconst __GeaStaticCssLengthOp *lengthSpecOps;
|
|
4070
|
+
\tconst __GeaStaticCssColorOp *colorOps;
|
|
4071
|
+
\tconst __GeaStaticCssColorVarOp *colorVarOps;
|
|
4072
|
+
\tconst __GeaStaticCssCustomLengthOp *customLengthOps;
|
|
4073
|
+
\tconst __GeaStaticCssCustomColorOp *customColorOps;
|
|
4074
|
+
\tconst __GeaStaticCssSelectorOnlyOp *boxShadowNoneOps;
|
|
4075
|
+
\tconst __GeaStaticCssNamedOp *fontFamilyOps;
|
|
4076
|
+
\tconst __GeaStaticCssLengthOnlyOp *filterBlurOps;
|
|
4077
|
+
\tconst __GeaStaticCssLineHeightOp *lineHeightOps;
|
|
4078
|
+
};
|
|
4079
|
+
auto __gea_register_static_css_tape = [&](const __GeaStaticCssTape &tape) {
|
|
4080
|
+
\tconst auto *propertyIt = tape.propertyOps;
|
|
4081
|
+
\tconst auto *lengthIt = tape.lengthOps;
|
|
4082
|
+
\tconst auto *lengthSpecIt = tape.lengthSpecOps;
|
|
4083
|
+
\tconst auto *colorIt = tape.colorOps;
|
|
4084
|
+
\tconst auto *colorVarIt = tape.colorVarOps;
|
|
4085
|
+
\tconst auto *customLengthIt = tape.customLengthOps;
|
|
4086
|
+
\tconst auto *customColorIt = tape.customColorOps;
|
|
4087
|
+
\tconst auto *boxShadowNoneIt = tape.boxShadowNoneOps;
|
|
4088
|
+
\tconst auto *fontFamilyIt = tape.fontFamilyOps;
|
|
4089
|
+
\tconst auto *filterBlurIt = tape.filterBlurOps;
|
|
4090
|
+
\tconst auto *lineHeightIt = tape.lineHeightOps;
|
|
4091
|
+
\tfor (std::size_t step = 0; step < tape.orderCount; ++step) {
|
|
4092
|
+
\t\tconst auto kind = tape.order[step];
|
|
4017
4093
|
\t\tswitch (kind) {
|
|
4018
4094
|
\t\tcase __GeaStaticCssTapeKind::Property: {
|
|
4019
4095
|
\t\t\tconst auto &op = *propertyIt++;
|
|
@@ -4114,12 +4190,27 @@ function compactStaticCssTapeCalls(calls) {
|
|
|
4114
4190
|
}
|
|
4115
4191
|
usedTape = true
|
|
4116
4192
|
const order = chunk.map((entry) => `__GeaStaticCssTapeKind::${entry.kind}`).join(', ')
|
|
4117
|
-
const
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4193
|
+
const opTypes = {
|
|
4194
|
+
Property: '__GeaStaticCssPropertyOp',
|
|
4195
|
+
Length: '__GeaStaticCssLengthOp',
|
|
4196
|
+
LengthSpec: '__GeaStaticCssLengthOp',
|
|
4197
|
+
Color: '__GeaStaticCssColorOp',
|
|
4198
|
+
ColorVar: '__GeaStaticCssColorVarOp',
|
|
4199
|
+
CustomLength: '__GeaStaticCssCustomLengthOp',
|
|
4200
|
+
CustomColor: '__GeaStaticCssCustomColorOp',
|
|
4201
|
+
BoxShadowNone: '__GeaStaticCssSelectorOnlyOp',
|
|
4202
|
+
FontFamily: '__GeaStaticCssNamedOp',
|
|
4203
|
+
FilterBlur: '__GeaStaticCssLengthOnlyOp',
|
|
4204
|
+
LineHeight: '__GeaStaticCssLineHeightOp',
|
|
4121
4205
|
}
|
|
4122
|
-
|
|
4206
|
+
const arrays = [`\tstatic constexpr __GeaStaticCssTapeKind order[] = {${order}};`]
|
|
4207
|
+
const pointers = kinds.map((kind) => {
|
|
4208
|
+
const entries = chunk.filter((entry) => entry.kind === kind).map((entry) => entry.code)
|
|
4209
|
+
if (entries.length === 0) return 'nullptr'
|
|
4210
|
+
arrays.push(`\tstatic constexpr ${opTypes[kind]} ops${kind}[] = {\n${entries.map((entry) => `\t\t${entry}`).join(',\n')}\n\t};`)
|
|
4211
|
+
return `ops${kind}`
|
|
4212
|
+
})
|
|
4213
|
+
out.push(`{\n${arrays.join('\n')}\n\t__gea_register_static_css_tape({${chunk.length}, order, ${pointers.join(', ')}});\n}`)
|
|
4123
4214
|
chunk = []
|
|
4124
4215
|
}
|
|
4125
4216
|
for (const call of calls) {
|
|
@@ -4135,6 +4226,7 @@ function compactStaticCssTapeCalls(calls) {
|
|
|
4135
4226
|
return { calls: out, usedTape, stringLiterals }
|
|
4136
4227
|
}
|
|
4137
4228
|
|
|
4229
|
+
let staticCssRegistrationCalls = []
|
|
4138
4230
|
function cssRegistrationCode(viteOutDir) {
|
|
4139
4231
|
const calls = []
|
|
4140
4232
|
staticCssLengthExpressionCounter = 0
|
|
@@ -4153,6 +4245,10 @@ function cssRegistrationCode(viteOutDir) {
|
|
|
4153
4245
|
emitCssRules(stripAtBlocks(block.body), block.condition, calls)
|
|
4154
4246
|
}
|
|
4155
4247
|
}
|
|
4248
|
+
// The calls themselves, before the tape packs them: a target that resolves
|
|
4249
|
+
// styles at build time (the Pebble compiled UI) reads these rather than
|
|
4250
|
+
// re-deriving the cascade from the CSS text.
|
|
4251
|
+
staticCssRegistrationCalls = calls
|
|
4156
4252
|
if (calls.length === 0) return ''
|
|
4157
4253
|
const compacted = compactStaticCssTapeCalls(calls)
|
|
4158
4254
|
const tapePrelude = compacted.usedTape ? staticCssTapePrelude(compacted.stringLiterals) : ''
|
|
@@ -4359,6 +4455,7 @@ const viteBundle = findFirstJsFile(viteOutDir)
|
|
|
4359
4455
|
if (!viteBundle) fail(`Vite produced no JS bundle in ${viteOutDir}`)
|
|
4360
4456
|
const cssPrelude = geaEmbeddedCompat ? cssRegistrationCode(viteOutDir) : ''
|
|
4361
4457
|
const cssPreludePath = path.join(outDir, 'gea-style-registration.cppfrag')
|
|
4458
|
+
fs.writeFileSync(path.join(outDir, 'gea-style-registration.calls.json'), JSON.stringify(staticCssRegistrationCalls, null, 1) + '\n')
|
|
4362
4459
|
if (cssPrelude || cppPreludeSymbol) {
|
|
4363
4460
|
fs.writeFileSync(cssPreludePath, cssPrelude)
|
|
4364
4461
|
} else {
|