drawnui-react 0.1.0-preview.2 → 0.1.0-preview.21
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 +17 -4
- package/SKIPPED.md +33 -27
- package/dist/controls/AnimatedFramesRenderer.d.ts +7 -0
- package/dist/controls/AnimatedFramesRenderer.js +16 -1
- package/dist/controls/DrawnGame.d.ts +40 -0
- package/dist/controls/DrawnGame.js +64 -0
- package/dist/controls/GridStructure.d.ts +16 -2
- package/dist/controls/GridStructure.js +40 -4
- package/dist/controls/SkiaBackdrop.d.ts +8 -2
- package/dist/controls/SkiaBackdrop.js +48 -8
- package/dist/controls/SkiaButton.d.ts +19 -2
- package/dist/controls/SkiaButton.js +41 -11
- package/dist/controls/SkiaCarousel.d.ts +9 -1
- package/dist/controls/SkiaCarousel.js +16 -3
- package/dist/controls/SkiaCheckbox.d.ts +0 -1
- package/dist/controls/SkiaCheckbox.js +0 -6
- package/dist/controls/SkiaDrawer.d.ts +2 -0
- package/dist/controls/SkiaDrawer.js +2 -0
- package/dist/controls/SkiaEditor.d.ts +12 -1
- package/dist/controls/SkiaEditor.js +46 -19
- package/dist/controls/SkiaGif.d.ts +3 -0
- package/dist/controls/SkiaGif.js +12 -2
- package/dist/controls/SkiaImage.js +15 -10
- package/dist/controls/SkiaLabel.d.ts +54 -3
- package/dist/controls/SkiaLabel.js +235 -52
- package/dist/controls/SkiaLabelFps.d.ts +16 -0
- package/dist/controls/SkiaLabelFps.js +41 -0
- package/dist/controls/SkiaLayout.d.ts +64 -7
- package/dist/controls/SkiaLayout.js +316 -19
- package/dist/controls/SkiaLottie.js +4 -2
- package/dist/controls/SkiaProgress.d.ts +2 -1
- package/dist/controls/SkiaProgress.js +6 -3
- package/dist/controls/SkiaRadioButton.js +4 -3
- package/dist/controls/SkiaScroll.d.ts +35 -5
- package/dist/controls/SkiaScroll.js +233 -23
- package/dist/controls/SkiaScrollBar.d.ts +27 -0
- package/dist/controls/SkiaScrollBar.js +51 -2
- package/dist/controls/SkiaShaderCarousel.d.ts +5 -0
- package/dist/controls/SkiaShaderCarousel.js +5 -0
- package/dist/controls/SkiaShape.d.ts +13 -2
- package/dist/controls/SkiaShape.js +50 -10
- package/dist/controls/SkiaSlider.d.ts +20 -2
- package/dist/controls/SkiaSlider.js +59 -5
- package/dist/controls/SkiaSprite.d.ts +1 -0
- package/dist/controls/SkiaSprite.js +4 -0
- package/dist/controls/SkiaSvg.js +1 -1
- package/dist/controls/SkiaSwitch.d.ts +0 -1
- package/dist/controls/SkiaSwitch.js +0 -6
- package/dist/controls/SkiaToggle.d.ts +25 -5
- package/dist/controls/SkiaToggle.js +58 -5
- package/dist/controls/SnappingLayout.d.ts +12 -1
- package/dist/controls/SnappingLayout.js +19 -1
- package/dist/core/Accessibility.d.ts +80 -0
- package/dist/core/Accessibility.js +365 -8
- package/dist/core/Animators.d.ts +37 -1
- package/dist/core/Animators.js +102 -9
- package/dist/core/Canvas.d.ts +108 -7
- package/dist/core/Canvas.js +363 -35
- package/dist/core/Easing.d.ts +12 -1
- package/dist/core/Easing.js +25 -1
- package/dist/core/Gestures.d.ts +48 -2
- package/dist/core/Gestures.js +95 -3
- package/dist/core/Hover.d.ts +47 -0
- package/dist/core/Hover.js +134 -0
- package/dist/core/KeyboardManager.d.ts +13 -0
- package/dist/core/KeyboardManager.js +18 -0
- package/dist/core/ScrollAnimators.js +9 -0
- package/dist/core/SkiaControl.d.ts +216 -7
- package/dist/core/SkiaControl.js +516 -59
- package/dist/core/SkiaEffect.d.ts +17 -0
- package/dist/core/SkiaEffect.js +43 -8
- package/dist/core/SkiaImageManager.js +1 -1
- package/dist/core/Styles.d.ts +51 -0
- package/dist/core/Styles.js +92 -0
- package/dist/core/Super.d.ts +17 -1
- package/dist/core/Super.js +35 -4
- package/dist/core/ViewsAdapter.d.ts +7 -2
- package/dist/core/ViewsAdapter.js +10 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/react/SkiaShell.js +33 -14
- package/dist/react/index.d.ts +15 -4
- package/dist/react/index.js +102 -15
- package/dist/react/reconciler.js +34 -12
- package/dist/vite/index.d.ts +9 -0
- package/dist/vite/index.js +36 -3
- package/package.json +33 -3
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { SKPoint } from "../core/Gestures";
|
|
2
2
|
import { Super } from "../core/Super";
|
|
3
|
-
import { SkiaValueAnimator } from "../core/Animators";
|
|
4
3
|
import { ResolveControlStyle } from "../core/ControlStyle";
|
|
5
4
|
import { KeyboardManager } from "../core/KeyboardManager";
|
|
6
5
|
import { TextInputProxy } from "../core/TextInputProxy";
|
|
@@ -67,13 +66,19 @@ export class SkiaEditor extends SkiaShape {
|
|
|
67
66
|
placeholder = new SkiaLabel();
|
|
68
67
|
scrollX = 0;
|
|
69
68
|
scrollY = 0;
|
|
70
|
-
|
|
69
|
+
/** The caret blinks on a timer, asleep between blinks: no frame runs while it waits (DrawnUi.Rust editor_rules). */
|
|
70
|
+
blinkTimer = 0;
|
|
71
71
|
caretVisible = true;
|
|
72
72
|
subscribed = false;
|
|
73
73
|
stubSelectionStop = -1;
|
|
74
74
|
selectionMovingEdge = -1;
|
|
75
75
|
onKeyDown = (key, e) => this.OnKeyDown(key, e);
|
|
76
|
-
onKeyChar = (ch, e) => {
|
|
76
|
+
onKeyChar = (ch, e) => {
|
|
77
|
+
if (KeyboardManager.IsOwnedByElement(e) || KeyboardManager.IsInputMethodKey(e))
|
|
78
|
+
return; // a page control or the IME owns it
|
|
79
|
+
e.preventDefault();
|
|
80
|
+
this.StubTypeText(ch);
|
|
81
|
+
};
|
|
77
82
|
selectionAnchor = -1;
|
|
78
83
|
dragSelecting = false;
|
|
79
84
|
styleApplied = {};
|
|
@@ -93,15 +98,6 @@ export class SkiaEditor extends SkiaShape {
|
|
|
93
98
|
this.placeholder.IsVisible = false;
|
|
94
99
|
this.AddSubView(this.placeholder);
|
|
95
100
|
this.AddSubView(this.Label);
|
|
96
|
-
this.blink.mMinValue = 0;
|
|
97
|
-
this.blink.mMaxValue = 1;
|
|
98
|
-
this.blink.Speed = 1000;
|
|
99
|
-
this.blink.Repeat = -1;
|
|
100
|
-
this.blink.OnUpdated = (v) => { const visible = v < 0.5; if (visible !== this.caretVisible) {
|
|
101
|
-
this.caretVisible = visible;
|
|
102
|
-
this.InvalidateCache();
|
|
103
|
-
this.RepaintComposition();
|
|
104
|
-
} };
|
|
105
101
|
this.ApplyControlStyleVisuals();
|
|
106
102
|
this.UpdateLabel();
|
|
107
103
|
}
|
|
@@ -192,9 +188,22 @@ export class SkiaEditor extends SkiaShape {
|
|
|
192
188
|
this.selectionLength = l;
|
|
193
189
|
this.OnCursorMoved();
|
|
194
190
|
}
|
|
191
|
+
/** Shows the caret for a full half second, then blinks every 500 ms. */
|
|
192
|
+
StartBlink() {
|
|
193
|
+
this.StopBlink();
|
|
194
|
+
this.caretVisible = true;
|
|
195
|
+
this.blinkTimer = window.setInterval(() => { this.caretVisible = !this.caretVisible; this.InvalidateCache(); this.RepaintComposition(); }, 500);
|
|
196
|
+
}
|
|
197
|
+
StopBlink() { if (this.blinkTimer) {
|
|
198
|
+
clearInterval(this.blinkTimer);
|
|
199
|
+
this.blinkTimer = 0;
|
|
200
|
+
} }
|
|
195
201
|
OnCursorMoved() {
|
|
196
202
|
this.ScrollToCaret();
|
|
197
|
-
this.
|
|
203
|
+
if (this.isFocused)
|
|
204
|
+
this.StartBlink();
|
|
205
|
+
else
|
|
206
|
+
this.caretVisible = true;
|
|
198
207
|
TextInputProxy.Sync(this);
|
|
199
208
|
this.CursorMoved?.(this);
|
|
200
209
|
this.InvalidateCache();
|
|
@@ -210,8 +219,7 @@ export class SkiaEditor extends SkiaShape {
|
|
|
210
219
|
SkiaEditor.Focused.IsFocused = false;
|
|
211
220
|
SkiaEditor.Focused = this;
|
|
212
221
|
this.SetFocusNative(true);
|
|
213
|
-
this.
|
|
214
|
-
this.blink.Start();
|
|
222
|
+
this.StartBlink();
|
|
215
223
|
}
|
|
216
224
|
else {
|
|
217
225
|
if (SkiaEditor.Focused === this)
|
|
@@ -220,7 +228,7 @@ export class SkiaEditor extends SkiaShape {
|
|
|
220
228
|
this.dragSelecting = false;
|
|
221
229
|
this.stubSelectionStop = -1;
|
|
222
230
|
this.selectionMovingEdge = -1;
|
|
223
|
-
this.
|
|
231
|
+
this.StopBlink();
|
|
224
232
|
this.SetFocusNative(false);
|
|
225
233
|
}
|
|
226
234
|
this.FocusChanged?.(this, v);
|
|
@@ -305,6 +313,14 @@ export class SkiaEditor extends SkiaShape {
|
|
|
305
313
|
MeasureAbsolute(w, h, scale) {
|
|
306
314
|
const px = this.Padding.HorizontalThickness * scale, py = this.Padding.VerticalThickness * scale;
|
|
307
315
|
const innerW = isFinite(w) ? Math.max(0, w - px) : Infinity;
|
|
316
|
+
// Single-line: the label is Start-aligned and measures to its content, so Center / End alignment had nothing to
|
|
317
|
+
// align in. Give it the field as a MINIMUM: short text centers in the field, longer text still grows past it and
|
|
318
|
+
// scrolls (C# 2e334ddd).
|
|
319
|
+
const minWidth = !this.IsMultiline && this.horizontalTextAlignment !== "Start" && isFinite(innerW) && innerW > 0 ? innerW / scale : -1;
|
|
320
|
+
if (this.Label.MinimumWidthRequest !== minWidth) {
|
|
321
|
+
this.Label.MinimumWidthRequest = minWidth;
|
|
322
|
+
this.Label.NeedMeasure = true;
|
|
323
|
+
}
|
|
308
324
|
const labelSize = this.Label.Measure(this.IsMultiline ? innerW : Infinity, Infinity, scale);
|
|
309
325
|
if (this.placeholder.IsVisible)
|
|
310
326
|
this.placeholder.Measure(innerW, Infinity, scale);
|
|
@@ -500,7 +516,15 @@ export class SkiaEditor extends SkiaShape {
|
|
|
500
516
|
}
|
|
501
517
|
return this;
|
|
502
518
|
}
|
|
503
|
-
|
|
519
|
+
/** A text field is a Tab stop by default, like a native text box, with no Tapped handler needed. */
|
|
520
|
+
DefaultAccessibilityCanInteract() { return true; }
|
|
521
|
+
/** Keyboard navigation reached the field (Tab) or left it: take the caret and the input sink like a native text box, or release them. */
|
|
522
|
+
OnAccessibilityFocused(focused) { this.IsFocused = focused; }
|
|
523
|
+
/** Enter / Space on the field while it has no caret start editing; while editing they are text. */
|
|
524
|
+
OnAccessibilityActivated() { if (!this.IsFocused)
|
|
525
|
+
this.OnAccessibilityFocused(true); }
|
|
526
|
+
/** While editing, arrows, Home / End and PageUp / PageDown belong to the text: they never move a surrounding group. */
|
|
527
|
+
OnAccessibilityKey(_key) { return this.IsFocused; }
|
|
504
528
|
DefaultAccessibilityLabel() { return this.text || this.placeholderText || undefined; }
|
|
505
529
|
// ---- editing API (C# names) ----
|
|
506
530
|
Submit() {
|
|
@@ -580,6 +604,10 @@ export class SkiaEditor extends SkiaShape {
|
|
|
580
604
|
OnKeyDown(key, e) {
|
|
581
605
|
const shift = KeyboardManager.IsShiftPressed, ctrl = KeyboardManager.IsControlPressed, alt = KeyboardManager.IsAltPressed;
|
|
582
606
|
const handled = () => e.preventDefault();
|
|
607
|
+
// keys of another element (a page field or button, an overlay node) and of the input method are not the editor's:
|
|
608
|
+
// a composition keeps its arrows, Escape and Backspace (C# 845b26e9, GitHub #231)
|
|
609
|
+
if (KeyboardManager.IsInputMethodKey(e) || (KeyboardManager.IsOwnedByElement(e) && !TextInputProxy.IsProxyTarget(e.target)))
|
|
610
|
+
return;
|
|
583
611
|
// with the hidden textarea focused these keys become input / clipboard events there and are applied from those
|
|
584
612
|
if (TextInputProxy.IsActive(this) && TextInputProxy.IsProxyTarget(e.target) && (key === "Backspace" || key === "Delete" || key === "Enter" || key === "NumpadEnter" || (ctrl && (key === "KeyC" || key === "KeyX" || key === "KeyV"))))
|
|
585
613
|
return;
|
|
@@ -794,8 +822,7 @@ export class SkiaEditor extends SkiaShape {
|
|
|
794
822
|
return out;
|
|
795
823
|
}
|
|
796
824
|
OnDisposing() {
|
|
797
|
-
this.
|
|
798
|
-
this.blink.Dispose();
|
|
825
|
+
this.StopBlink();
|
|
799
826
|
if (SkiaEditor.Focused === this)
|
|
800
827
|
SkiaEditor.Focused = undefined;
|
|
801
828
|
this.SetFocusNative(false);
|
|
@@ -14,6 +14,8 @@ export declare class GifAnimation {
|
|
|
14
14
|
private positionsMs;
|
|
15
15
|
/** Negative = the last frame. */
|
|
16
16
|
SeekFrame(frame: number): void;
|
|
17
|
+
/** Start (ms) of the frame after the one at `msTime`; DurationMs after the last one. */
|
|
18
|
+
NextFrameStartMs(msTime: number): number;
|
|
17
19
|
GetFrameNumber(msTime: number): number;
|
|
18
20
|
/** Decodes every frame of an encoded GIF (CanvasKit AnimatedImage). */
|
|
19
21
|
LoadFromBytes(bytes: ArrayBuffer): void;
|
|
@@ -37,6 +39,7 @@ export declare class SkiaGif extends AnimatedFramesRenderer {
|
|
|
37
39
|
set Source(v: string);
|
|
38
40
|
Start(delayMs?: number): void;
|
|
39
41
|
protected OnAnimatorUpdated(value: number): void;
|
|
42
|
+
protected NextChangeMs(value: number): number | undefined;
|
|
40
43
|
/** Seeks by time in ms (the animator range is 0..DurationMs). */
|
|
41
44
|
protected OnAnimatorSeeking(time: number): void;
|
|
42
45
|
protected OnAnimatorInitializing(): void;
|
package/dist/controls/SkiaGif.js
CHANGED
|
@@ -21,6 +21,13 @@ export class GifAnimation {
|
|
|
21
21
|
if (frame >= 0 && frame <= this.TotalFrames - 1)
|
|
22
22
|
this.Frame = this.Frames[frame];
|
|
23
23
|
}
|
|
24
|
+
/** Start (ms) of the frame after the one at `msTime`; DurationMs after the last one. */
|
|
25
|
+
NextFrameStartMs(msTime) {
|
|
26
|
+
for (let i = 0; i < this.positionsMs.length; i++)
|
|
27
|
+
if (msTime < this.positionsMs[i])
|
|
28
|
+
return this.positionsMs[i];
|
|
29
|
+
return this.DurationMs;
|
|
30
|
+
}
|
|
24
31
|
GetFrameNumber(msTime) {
|
|
25
32
|
if (this.positionsMs.length === 0 || this.DurationMs <= 0)
|
|
26
33
|
return 0;
|
|
@@ -87,7 +94,9 @@ export class SkiaGif extends AnimatedFramesRenderer {
|
|
|
87
94
|
loadGeneration = 0;
|
|
88
95
|
constructor() {
|
|
89
96
|
super();
|
|
90
|
-
|
|
97
|
+
// C# ImageDoubleBuffered pays off where a thread bakes the bitmap; on the web it is one offscreen pass per frame
|
|
98
|
+
// change, so the web engines draw a GIF frame with no cache (drawnui-cross rule 3)
|
|
99
|
+
this.UseCache = "None";
|
|
91
100
|
}
|
|
92
101
|
get Source() { return this.source; }
|
|
93
102
|
set Source(v) { if (this.source !== v) {
|
|
@@ -97,6 +106,7 @@ export class SkiaGif extends AnimatedFramesRenderer {
|
|
|
97
106
|
Start(delayMs = 0) { if ((this.Animation?.TotalFrames ?? 0) > 0)
|
|
98
107
|
super.Start(delayMs); }
|
|
99
108
|
OnAnimatorUpdated(value) { this.Seek(value); }
|
|
109
|
+
NextChangeMs(value) { return this.Animation && this.Animation.DurationMs > 0 ? this.Animation.NextFrameStartMs(value) : undefined; }
|
|
100
110
|
/** Seeks by time in ms (the animator range is 0..DurationMs). */
|
|
101
111
|
OnAnimatorSeeking(time) {
|
|
102
112
|
const a = this.Animation;
|
|
@@ -158,7 +168,7 @@ export class SkiaGif extends AnimatedFramesRenderer {
|
|
|
158
168
|
async LoadSource(source) {
|
|
159
169
|
if (!source)
|
|
160
170
|
return undefined;
|
|
161
|
-
const r = await fetch(source);
|
|
171
|
+
const r = await fetch(Super.ResolveAssetUrl(source));
|
|
162
172
|
if (!r.ok)
|
|
163
173
|
throw new Error(`${r.status} ${source}`);
|
|
164
174
|
const animation = new GifAnimation();
|
|
@@ -164,20 +164,25 @@ export class SkiaImage extends SkiaControl {
|
|
|
164
164
|
MeasureAbsolute(widthConstraint, heightConstraint, scale) {
|
|
165
165
|
const img = this.LoadedSource;
|
|
166
166
|
let w = widthConstraint, h = heightConstraint;
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
else if (!isFinite(h) && isFinite(w))
|
|
172
|
-
h = w / aspect;
|
|
167
|
+
// nothing loaded: the box it is offered (C# OnMeasuring), an unbounded side 0
|
|
168
|
+
if (!img) {
|
|
169
|
+
this.AspectScale = { X: 0, Y: 0 };
|
|
170
|
+
return ScaledSize.FromPixels(isFinite(w) ? w : 0, isFinite(h) ? h : 0, scale);
|
|
173
171
|
}
|
|
174
|
-
|
|
172
|
+
const iw = img.width(), ih = img.height();
|
|
173
|
+
if (!isFinite(w) && isFinite(h))
|
|
174
|
+
w = h * iw / ih;
|
|
175
|
+
else if (!isFinite(h) && isFinite(w))
|
|
176
|
+
h = w * ih / iw;
|
|
177
|
+
if (!isFinite(w) || !isFinite(h) || iw <= 0 || ih <= 0) {
|
|
175
178
|
this.AspectScale = { X: 0, Y: 0 };
|
|
176
179
|
return ScaledSize.FromPixels(0, 0, scale);
|
|
177
180
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
+
// C# OnMeasuring / DrawnUi.Rust: an auto-sized side is the bitmap's pixels scaled by the aspect for this box, never
|
|
182
|
+
// more than the box (a Fill or requested side still takes its box in Measure)
|
|
183
|
+
const s = SkiaImage.RescaleAspect(iw, ih, SKRect.Create(0, 0, w, h), this.Aspect);
|
|
184
|
+
this.AspectScale = s;
|
|
185
|
+
return ScaledSize.FromPixels(Math.min(iw * s.X, w), Math.min(ih * s.Y, h), scale);
|
|
181
186
|
}
|
|
182
187
|
Paint(ctx) {
|
|
183
188
|
const img = this.LoadedSource;
|
|
@@ -43,6 +43,8 @@ export declare class SkiaLabel extends SkiaControl {
|
|
|
43
43
|
private verticalTextAlignment;
|
|
44
44
|
private lineSpacing;
|
|
45
45
|
private lineHeight;
|
|
46
|
+
private paragraphSpacing;
|
|
47
|
+
private characterSpacing;
|
|
46
48
|
private textTransform;
|
|
47
49
|
private padding;
|
|
48
50
|
/** Styled fragments; when not empty they replace `Text` (same precedence as C#). */
|
|
@@ -53,6 +55,8 @@ export declare class SkiaLabel extends SkiaControl {
|
|
|
53
55
|
protected DefaultAccessibilityLabel(): string | undefined;
|
|
54
56
|
constructor();
|
|
55
57
|
private Set;
|
|
58
|
+
/** A property that changes only the look (a color): no layout change, see UpdateDraw. */
|
|
59
|
+
private SetLook;
|
|
56
60
|
get Text(): string;
|
|
57
61
|
set Text(v: string);
|
|
58
62
|
get FontSize(): number;
|
|
@@ -84,6 +88,18 @@ export declare class SkiaLabel extends SkiaControl {
|
|
|
84
88
|
/** Multiplier applied to the natural line height (ascent + descent). */
|
|
85
89
|
get LineHeight(): number;
|
|
86
90
|
set LineHeight(v: number);
|
|
91
|
+
/**
|
|
92
|
+
* Space above every paragraph after the first, in lines (C# ParagraphSpacing; 0 here as DrawnUi.Rust, C# 0.25). A
|
|
93
|
+
* paragraph starts after "\n"; U+2028 breaks the line inside a paragraph.
|
|
94
|
+
*/
|
|
95
|
+
get ParagraphSpacing(): number;
|
|
96
|
+
set ParagraphSpacing(v: number);
|
|
97
|
+
/**
|
|
98
|
+
* C# CharacterSpacing: 1 = the font's own spacing; every glyph is followed by (CharacterSpacing - 1) points more
|
|
99
|
+
* (less below 1), the line measures and wraps at the width it draws (C# 7cf1007c, DrawnUi.Rust label).
|
|
100
|
+
*/
|
|
101
|
+
get CharacterSpacing(): number;
|
|
102
|
+
set CharacterSpacing(v: number);
|
|
87
103
|
get TextTransform(): TextTransform;
|
|
88
104
|
set TextTransform(v: TextTransform);
|
|
89
105
|
get Padding(): Thickness;
|
|
@@ -97,17 +113,46 @@ export declare class SkiaLabel extends SkiaControl {
|
|
|
97
113
|
private mainFonts?;
|
|
98
114
|
private readonly fontsCache;
|
|
99
115
|
private readonly runCache;
|
|
116
|
+
/** CharacterSpacing in pixels at the measured scale: added after every glyph of a run (its Width includes them). */
|
|
117
|
+
private glyphSpacing;
|
|
100
118
|
private ResolveFonts;
|
|
101
119
|
/** The label's own style, and the base every span inherits from. */
|
|
102
120
|
private ResolveMainFonts;
|
|
103
121
|
private ResolveSpanFonts;
|
|
104
|
-
private
|
|
122
|
+
private Advance;
|
|
123
|
+
private static readonly Ignorable;
|
|
124
|
+
/**
|
|
125
|
+
* Default-ignorable code points (zero width space, joiners, direction marks, word joiners, variation selectors such
|
|
126
|
+
* as U+FE0F after an emoji, tags) that none of the fonts has draw nothing and take no room, never the missing-glyph
|
|
127
|
+
* box (DrawnUi.Rust label_ignorables; text is not shaped here, C# hides them by shaping).
|
|
128
|
+
*/
|
|
129
|
+
private static DropIgnorables;
|
|
105
130
|
/**
|
|
106
131
|
* Splits text into runs by glyph availability: the main font, or the first fallback that has a glyph where the
|
|
107
132
|
* main font has glyph 0. Spaces always stay on the main font (fallback faces often carry very wide spaces).
|
|
108
133
|
*/
|
|
109
134
|
private Segment;
|
|
110
135
|
private Width;
|
|
136
|
+
/** A line never starts with these (closing punctuation, small kana, the long vowel mark): JIS X 4051 kinsoku (C#). */
|
|
137
|
+
private static readonly NoBreakBefore;
|
|
138
|
+
/** A line never ends with these (opening brackets and quotes). */
|
|
139
|
+
private static readonly NoBreakAfter;
|
|
140
|
+
/** Chinese / Japanese: ideographs, kana, CJK punctuation, full-width forms (C# IsCjkAt). Korean breaks at spaces only. */
|
|
141
|
+
private static readonly Cjk;
|
|
142
|
+
private static CanBreakBetween;
|
|
143
|
+
/**
|
|
144
|
+
* C# CanBreakInsideWord: whether a line may break between text[index - 1] and text[index] (UTF-16 indexes) inside a
|
|
145
|
+
* space-free run: next to a Chinese or Japanese character, never before closing punctuation or small kana, never
|
|
146
|
+
* after an opening bracket, never inside a surrogate pair.
|
|
147
|
+
*/
|
|
148
|
+
static CanBreakInsideWord(text: string, index: number): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* C# FitAtBreak: the last place inside the word where a Chinese / Japanese line may break and `prefix` plus the word
|
|
151
|
+
* up to there still fits; code points from the word's start, 0 = none.
|
|
152
|
+
*/
|
|
153
|
+
private FitCjk;
|
|
154
|
+
/** The word cut after `count` code points: the head goes on a line, the rest follows. */
|
|
155
|
+
private SplitWord;
|
|
111
156
|
private Transform;
|
|
112
157
|
/**
|
|
113
158
|
* Paragraphs (split on "\n") of wrap tokens, built from Spans when present, else from Text.
|
|
@@ -116,11 +161,17 @@ export declare class SkiaLabel extends SkiaControl {
|
|
|
116
161
|
private Tokenize;
|
|
117
162
|
private NewLine;
|
|
118
163
|
private Append;
|
|
119
|
-
/**
|
|
164
|
+
/**
|
|
165
|
+
* Word-wraps tokens into lines that fit maxWidth (Infinity = no wrap); keeps the lines that fit maxHeight (at least one)
|
|
166
|
+
* and MaxLines, the last kept one ending with a tail ellipsis (C# / DrawnUi.Rust: a label in a box too short for its
|
|
167
|
+
* text cuts it, not only MaxLines).
|
|
168
|
+
*/
|
|
120
169
|
private LayoutLines;
|
|
121
170
|
private LineHeightPx;
|
|
171
|
+
/** ParagraphSpacing above a line that starts a paragraph (after the first): that many of its lines, with their spacing. */
|
|
172
|
+
private ParagraphSpace;
|
|
122
173
|
private BlockHeight;
|
|
123
|
-
protected MeasureAbsolute(widthConstraint: number,
|
|
174
|
+
protected MeasureAbsolute(widthConstraint: number, heightConstraint: number, scale: number): ScaledSize;
|
|
124
175
|
/** C# GradientByLines: FillGradient spans each line's bounds (default) instead of the whole text block. */
|
|
125
176
|
GradientByLines: boolean;
|
|
126
177
|
/** C# KeepSpacesOnLineBreaks / NeedsGlyphPositions: accepted; glyph boxes are always available through GetGlyphBoxes. */
|