@aelionsdk/render-ir 1.2.0-rc.2 → 1.2.0-rc.4

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 CHANGED
@@ -9,7 +9,7 @@ evaluation for AelionSDK.
9
9
  npm install @aelionsdk/render-ir@next
10
10
  ```
11
11
 
12
- `next` currently resolves to `1.2.0-rc.2`. Product applications should use
12
+ `next` currently resolves to `1.2.0-rc.4`. Product applications should use
13
13
  `@aelionsdk/sdk`; direct use is for custom renderers, exporters and engine
14
14
  instrumentation.
15
15
 
@@ -38,8 +38,41 @@ export interface PortableTextStyle {
38
38
  readonly strokeWidthPx: number;
39
39
  readonly align: 'start' | 'center' | 'end';
40
40
  readonly direction: 'ltr' | 'rtl';
41
+ readonly backgroundFill: string;
42
+ readonly backgroundOpacity: number;
43
+ readonly backgroundPaddingPx: number;
44
+ readonly backgroundRadiusPx: number;
41
45
  }
42
46
  export declare function portableTextStyle(runStyle: JsonObject, paragraphStyle?: JsonObject, scale?: number): PortableTextStyle;
47
+ /** Whether a run's background plate contributes any pixels at its opacity. */
48
+ export declare function textBackgroundVisible(style: PortableTextStyle): boolean;
49
+ /**
50
+ * Rewrites a `#rgb`, `#rrggbb` or `rgb()` colour as `rgba()` with the given
51
+ * alpha. Colours the parser does not recognize are returned unchanged.
52
+ */
53
+ export declare function cssColorWithAlpha(color: string, alpha: number): string;
54
+ /**
55
+ * Pixels a run paints outside its glyph box, whichever of the stroke or the
56
+ * background plate's padding reaches further.
57
+ */
58
+ export declare function textPaintExtent(style: PortableTextStyle): number;
59
+ /** Largest {@link textPaintExtent} across every run in a text clip. */
60
+ export declare function textClipPaintExtent(clip: IrTextClip): number;
61
+ /**
62
+ * Grows a layout box by `pad` on every side so stroke and background pixels
63
+ * stay inside the rasterized target. Non-positive padding returns `box` as-is.
64
+ */
65
+ export declare function inflateTextBox(box: {
66
+ readonly x: number;
67
+ readonly y: number;
68
+ readonly width: number;
69
+ readonly height: number;
70
+ }, pad: number): {
71
+ readonly x: number;
72
+ readonly y: number;
73
+ readonly width: number;
74
+ readonly height: number;
75
+ };
43
76
  export declare function portableGlyphAdvance(character: string, style: PortableTextStyle): number;
44
77
  /** Deterministic, host-independent line breaking used by Preview and Export. */
45
78
  export declare function layoutIrText(clip: IrTextClip): IrTextLayout;
@@ -1 +1 @@
1
- {"version":3,"file":"text-layout.d.ts","sourceRoot":"","sources":["../src/text-layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,YAAY,CAAC;AAQxD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,gCAAgC,CAAC;IACrD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC3C,QAAQ,CAAC,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC;CACnC;AAUD,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,UAAU,EACpB,cAAc,GAAE,UAAe,EAC/B,KAAK,SAAI,GACR,iBAAiB,CAsBnB;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAaxF;AA8HD,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,CA2B3D"}
1
+ {"version":3,"file":"text-layout.d.ts","sourceRoot":"","sources":["../src/text-layout.ts"],"names":[],"mappings":"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"}
@@ -29,8 +29,93 @@ export function portableTextStyle(runStyle, paragraphStyle = {}, scale = 1) {
29
29
  strokeWidthPx: Math.max(0, finite(combined.strokeWidthPx, 0) * scale),
30
30
  align: align === 'center' || align === 'end' ? align : 'start',
31
31
  direction: direction === 'rtl' ? 'rtl' : 'ltr',
32
+ backgroundFill: text(combined.backgroundFill, '#000000'),
33
+ backgroundOpacity: Math.max(0, Math.min(1, finite(combined.backgroundOpacity, 0))),
34
+ backgroundPaddingPx: Math.max(0, combined.backgroundPaddingPx === undefined
35
+ ? fontSizePx * 0.25
36
+ : finite(combined.backgroundPaddingPx, fontSizePx * 0.25) * scale),
37
+ backgroundRadiusPx: Math.max(0, combined.backgroundRadiusPx === undefined
38
+ ? fontSizePx * 0.15
39
+ : finite(combined.backgroundRadiusPx, fontSizePx * 0.15) * scale),
32
40
  };
33
41
  }
42
+ /** Whether a run's background plate contributes any pixels at its opacity. */
43
+ export function textBackgroundVisible(style) {
44
+ return style.backgroundOpacity > 0.001;
45
+ }
46
+ /**
47
+ * Rewrites a `#rgb`, `#rrggbb` or `rgb()` colour as `rgba()` with the given
48
+ * alpha. Colours the parser does not recognize are returned unchanged.
49
+ */
50
+ export function cssColorWithAlpha(color, alpha) {
51
+ const rgb = parseCssRgb(color);
52
+ const clamped = Math.max(0, Math.min(1, alpha));
53
+ if (rgb === undefined)
54
+ return color;
55
+ return `rgba(${rgb[0].toString()}, ${rgb[1].toString()}, ${rgb[2].toString()}, ${clamped.toString()})`;
56
+ }
57
+ /**
58
+ * Pixels a run paints outside its glyph box, whichever of the stroke or the
59
+ * background plate's padding reaches further.
60
+ */
61
+ export function textPaintExtent(style) {
62
+ const pad = textBackgroundVisible(style) ? style.backgroundPaddingPx : 0;
63
+ return Math.max(style.strokeWidthPx, pad);
64
+ }
65
+ /** Largest {@link textPaintExtent} across every run in a text clip. */
66
+ export function textClipPaintExtent(clip) {
67
+ let pad = 0;
68
+ for (const paragraph of clip.paragraphs) {
69
+ for (const run of paragraph.runs) {
70
+ pad = Math.max(pad, textPaintExtent(portableTextStyle(run.style, paragraph.style)));
71
+ }
72
+ }
73
+ return pad;
74
+ }
75
+ /**
76
+ * Grows a layout box by `pad` on every side so stroke and background pixels
77
+ * stay inside the rasterized target. Non-positive padding returns `box` as-is.
78
+ */
79
+ export function inflateTextBox(box, pad) {
80
+ if (pad <= 0)
81
+ return box;
82
+ return {
83
+ x: box.x - pad,
84
+ y: box.y - pad,
85
+ width: box.width + pad * 2,
86
+ height: box.height + pad * 2,
87
+ };
88
+ }
89
+ function parseCssRgb(color) {
90
+ const value = color.trim();
91
+ const hex6 = /^#([0-9a-f]{6})$/iu.exec(value);
92
+ if (hex6?.[1] !== undefined) {
93
+ const n = Number.parseInt(hex6[1], 16);
94
+ return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
95
+ }
96
+ const hex3 = /^#([0-9a-f]{3})$/iu.exec(value);
97
+ if (hex3?.[1] !== undefined) {
98
+ const raw = hex3[1];
99
+ const r = raw[0];
100
+ const g = raw[1];
101
+ const b = raw[2];
102
+ if (r === undefined || g === undefined || b === undefined)
103
+ return undefined;
104
+ return [
105
+ Number.parseInt(`${r}${r}`, 16),
106
+ Number.parseInt(`${g}${g}`, 16),
107
+ Number.parseInt(`${b}${b}`, 16),
108
+ ];
109
+ }
110
+ const rgb = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/u.exec(value);
111
+ if (rgb === null)
112
+ return undefined;
113
+ return [
114
+ Number.parseInt(rgb[1] ?? '0', 10),
115
+ Number.parseInt(rgb[2] ?? '0', 10),
116
+ Number.parseInt(rgb[3] ?? '0', 10),
117
+ ];
118
+ }
34
119
  export function portableGlyphAdvance(character, style) {
35
120
  const codePoint = character.codePointAt(0) ?? 0;
36
121
  const em = character === ' '
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aelionsdk/render-ir",
3
- "version": "1.2.0-rc.2",
3
+ "version": "1.2.0-rc.4",
4
4
  "description": "Incremental render intermediate representation compiler for AelionSDK",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,9 +34,9 @@
34
34
  "provenance": true
35
35
  },
36
36
  "dependencies": {
37
- "@aelionsdk/core": "1.2.0-rc.2",
38
- "@aelionsdk/material-compiler": "1.2.0-rc.2",
39
- "@aelionsdk/project-schema": "1.2.0-rc.2"
37
+ "@aelionsdk/core": "1.2.0-rc.4",
38
+ "@aelionsdk/material-compiler": "1.2.0-rc.4",
39
+ "@aelionsdk/project-schema": "1.2.0-rc.4"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsc -b",