@shopify/react-native-skia 2.2.8 → 2.2.9

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.
@@ -286,17 +286,6 @@ dependencies {
286
286
  }
287
287
  }
288
288
 
289
- afterEvaluate { project ->
290
- android.libraryVariants.all { variant ->
291
- def name = variant.name.capitalize()
292
- def javaCompileTask = variant.javaCompileProvider.get()
293
-
294
- task "jar${name}"(type: Jar, dependsOn: javaCompileTask) {
295
- from javaCompileTask.destinationDir
296
- }
297
- }
298
- }
299
-
300
289
  def localBuildDir = buildDir
301
290
  def headersConfiguration = configurations.extractHeaders
302
291
  def jniConfiguration = configurations.extractJNI
@@ -95,15 +95,47 @@ public:
95
95
  std::vector<para::LineMetrics> metrics;
96
96
  getObject()->getLineMetrics(metrics);
97
97
  auto returnValue = jsi::Array(runtime, metrics.size());
98
- auto height = 0;
98
+
99
99
  for (size_t i = 0; i < metrics.size(); ++i) {
100
- returnValue.setValueAtIndex(
101
- runtime, i,
102
- JsiSkRect::toValue(runtime, getContext(),
103
- SkRect::MakeXYWH(metrics[i].fLeft, height,
104
- metrics[i].fWidth,
105
- metrics[i].fHeight)));
106
- height += metrics[i].fHeight;
100
+ auto lineMetrics = jsi::Object(runtime);
101
+
102
+ // Text indices
103
+ lineMetrics.setProperty(runtime, "startIndex",
104
+ static_cast<double>(metrics[i].fStartIndex));
105
+ lineMetrics.setProperty(runtime, "endIndex",
106
+ static_cast<double>(metrics[i].fEndIndex));
107
+ lineMetrics.setProperty(runtime, "endExcludingWhitespaces",
108
+ static_cast<double>(metrics[i].fEndExcludingWhitespaces));
109
+ lineMetrics.setProperty(runtime, "endIncludingNewline",
110
+ static_cast<double>(metrics[i].fEndIncludingNewline));
111
+
112
+ // Line break info
113
+ lineMetrics.setProperty(runtime, "isHardBreak",
114
+ metrics[i].fHardBreak);
115
+
116
+ // Vertical metrics
117
+ lineMetrics.setProperty(runtime, "ascent",
118
+ static_cast<double>(metrics[i].fAscent));
119
+ lineMetrics.setProperty(runtime, "descent",
120
+ static_cast<double>(metrics[i].fDescent));
121
+ lineMetrics.setProperty(runtime, "height",
122
+ static_cast<double>(metrics[i].fHeight));
123
+
124
+ // Horizontal metrics
125
+ lineMetrics.setProperty(runtime, "width",
126
+ static_cast<double>(metrics[i].fWidth));
127
+ lineMetrics.setProperty(runtime, "left",
128
+ static_cast<double>(metrics[i].fLeft));
129
+
130
+ // Position
131
+ lineMetrics.setProperty(runtime, "baseline",
132
+ static_cast<double>(metrics[i].fBaseline));
133
+
134
+ // Line number
135
+ lineMetrics.setProperty(runtime, "lineNumber",
136
+ static_cast<double>(metrics[i].fLineNumber));
137
+
138
+ returnValue.setValueAtIndex(runtime, i, lineMetrics);
107
139
  }
108
140
  return returnValue;
109
141
  }
@@ -12,7 +12,7 @@ export declare class ParagraphAsset<Ctx extends EvalContext> extends SkiaObject<
12
12
  getLongestLine(): number;
13
13
  getGlyphPositionAtCoordinate(x: number, y: number): number;
14
14
  getRectsForRange(start: number, end: number): import("../../../../skia/types").SkRect[];
15
- getLineMetrics(): import("../../../../skia/types").SkRect[];
15
+ getLineMetrics(): import("../../../../skia/types").LineMetrics[];
16
16
  getRectsForPlaceholders(): import("../../../../skia/types").SkRectWithDirection[];
17
17
  __typename__: "Paragraph";
18
18
  dispose(): void;
@@ -2,6 +2,36 @@ import type { SkCanvas } from "../Canvas";
2
2
  import type { SkJSIInstance } from "../JsiInstance";
3
3
  import type { SkRect } from "../Rect";
4
4
  import type { TextDirection } from "./ParagraphStyle";
5
+ export interface LineMetrics {
6
+ /** The index in the text buffer the line begins. */
7
+ startIndex: number;
8
+ /** The index in the text buffer the line ends. */
9
+ endIndex: number;
10
+ endExcludingWhitespaces: number;
11
+ endIncludingNewline: number;
12
+ /** True if the line ends in a hard break (e.g. newline) */
13
+ isHardBreak: boolean;
14
+ /**
15
+ * The final computed ascent for the line. This can be impacted by
16
+ * the strut, height, scaling, as well as outlying runs that are very tall.
17
+ */
18
+ ascent: number;
19
+ /**
20
+ * The final computed descent for the line. This can be impacted by
21
+ * the strut, height, scaling, as well as outlying runs that are very tall.
22
+ */
23
+ descent: number;
24
+ /** round(ascent + descent) */
25
+ height: number;
26
+ /** width of the line */
27
+ width: number;
28
+ /** The left edge of the line. The right edge can be obtained with `left + width` */
29
+ left: number;
30
+ /** The y position of the baseline for this line from the top of the paragraph. */
31
+ baseline: number;
32
+ /** Zero indexed line number. */
33
+ lineNumber: number;
34
+ }
5
35
  export interface SkRectWithDirection {
6
36
  rect: SkRect;
7
37
  direction: TextDirection;
@@ -70,7 +100,7 @@ export interface SkParagraph extends SkJSIInstance<"Paragraph"> {
70
100
  * Returns the bounding boxes for all lines in the paragraph. This method
71
101
  * requires the layout method to have been called first.
72
102
  */
73
- getLineMetrics(): Array<SkRect>;
103
+ getLineMetrics(): LineMetrics[];
74
104
  /**
75
105
  * Returns a list of rects with direction info for the placeholders added
76
106
  * to the paragraph.
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["Paragraph.ts"],"sourcesContent":["import type { SkCanvas } from \"../Canvas\";\nimport type { SkJSIInstance } from \"../JsiInstance\";\nimport type { SkRect } from \"../Rect\";\n\nimport type { TextDirection } from \"./ParagraphStyle\";\n\nexport interface SkRectWithDirection {\n rect: SkRect;\n direction: TextDirection;\n}\n\nexport interface SkParagraph extends SkJSIInstance<\"Paragraph\"> {\n /**\n * Calculates the position of the the glyphs in the paragraph\n * @param width Max width of the paragraph\n */\n layout(width: number): void;\n /**\n * Paints the paragraph to the provded canvas\n * @param canvas Canvas to paint into\n * @param x X coordinate to paint at\n * @param y Y coordinate to paint at\n */\n paint(canvas: SkCanvas, x: number, y: number): void;\n /**\n * Returns the height of the paragraph. This method requires the layout\n * method to have been called first.\n */\n getHeight(): number;\n /**\n * Returns the max width of the paragraph. This method requires the layout\n * method to have been called first.\n */\n getMaxWidth(): number;\n /**\n * Returns the minimum intrinsic width of the paragraph.\n * The minimum intrinsic width is the width beyond which increasing the width of the paragraph\n * does not decrease the height. This is effectively the width at which the paragraph\n * can no longer wrap lines and is forced to overflow.\n * This method requires the layout method to have been called first.\n * @returns {number} The minimum intrinsic width of the paragraph.\n */\n getMinIntrinsicWidth(): number;\n /**\n * Returns the maximum intrinsic width of the paragraph.\n * The maximum intrinsic width is the width at which the paragraph can layout its content without line breaks,\n * meaning it's the width of the widest line or the widest word if the widest line is shorter than that.\n * This width represents the ideal width for the paragraph to display all content in a single line without overflow.\n * This method requires the layout method to have been called first.\n * @returns {number} The maximum intrinsic width of the paragraph.\n */\n getMaxIntrinsicWidth(): number;\n\n /**\n * Returns the width of the longest line in the paragraph.\n * This method requires the layout method to have been called first.\n */\n getLongestLine(): number;\n\n /**\n * Returns the index of the glyph at the given position. This method requires\n * the layout method to have been called first.\n * @param x X coordinate of the position\n * @param y Y coordinate of the position\n */\n getGlyphPositionAtCoordinate(x: number, y: number): number;\n /**\n * Returns the bounding boxes of the glyphs in the given range. This method\n * requires the layout method to have been called first.\n * @param start Start index of the range\n * @param end End index of the range\n */\n getRectsForRange(start: number, end: number): SkRect[];\n /**\n * Returns the bounding boxes for all lines in the paragraph. This method\n * requires the layout method to have been called first.\n */\n getLineMetrics(): Array<SkRect>;\n /**\n * Returns a list of rects with direction info for the placeholders added\n * to the paragraph.\n */\n getRectsForPlaceholders(): SkRectWithDirection[];\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["Paragraph.ts"],"sourcesContent":["import type { SkCanvas } from \"../Canvas\";\nimport type { SkJSIInstance } from \"../JsiInstance\";\nimport type { SkRect } from \"../Rect\";\n\nimport type { TextDirection } from \"./ParagraphStyle\";\n\nexport interface LineMetrics {\n /** The index in the text buffer the line begins. */\n startIndex: number;\n /** The index in the text buffer the line ends. */\n endIndex: number;\n endExcludingWhitespaces: number;\n endIncludingNewline: number;\n /** True if the line ends in a hard break (e.g. newline) */\n isHardBreak: boolean;\n /**\n * The final computed ascent for the line. This can be impacted by\n * the strut, height, scaling, as well as outlying runs that are very tall.\n */\n ascent: number;\n /**\n * The final computed descent for the line. This can be impacted by\n * the strut, height, scaling, as well as outlying runs that are very tall.\n */\n descent: number;\n /** round(ascent + descent) */\n height: number;\n /** width of the line */\n width: number;\n /** The left edge of the line. The right edge can be obtained with `left + width` */\n left: number;\n /** The y position of the baseline for this line from the top of the paragraph. */\n baseline: number;\n /** Zero indexed line number. */\n lineNumber: number;\n}\n\nexport interface SkRectWithDirection {\n rect: SkRect;\n direction: TextDirection;\n}\n\nexport interface SkParagraph extends SkJSIInstance<\"Paragraph\"> {\n /**\n * Calculates the position of the the glyphs in the paragraph\n * @param width Max width of the paragraph\n */\n layout(width: number): void;\n /**\n * Paints the paragraph to the provded canvas\n * @param canvas Canvas to paint into\n * @param x X coordinate to paint at\n * @param y Y coordinate to paint at\n */\n paint(canvas: SkCanvas, x: number, y: number): void;\n /**\n * Returns the height of the paragraph. This method requires the layout\n * method to have been called first.\n */\n getHeight(): number;\n /**\n * Returns the max width of the paragraph. This method requires the layout\n * method to have been called first.\n */\n getMaxWidth(): number;\n /**\n * Returns the minimum intrinsic width of the paragraph.\n * The minimum intrinsic width is the width beyond which increasing the width of the paragraph\n * does not decrease the height. This is effectively the width at which the paragraph\n * can no longer wrap lines and is forced to overflow.\n * This method requires the layout method to have been called first.\n * @returns {number} The minimum intrinsic width of the paragraph.\n */\n getMinIntrinsicWidth(): number;\n /**\n * Returns the maximum intrinsic width of the paragraph.\n * The maximum intrinsic width is the width at which the paragraph can layout its content without line breaks,\n * meaning it's the width of the widest line or the widest word if the widest line is shorter than that.\n * This width represents the ideal width for the paragraph to display all content in a single line without overflow.\n * This method requires the layout method to have been called first.\n * @returns {number} The maximum intrinsic width of the paragraph.\n */\n getMaxIntrinsicWidth(): number;\n\n /**\n * Returns the width of the longest line in the paragraph.\n * This method requires the layout method to have been called first.\n */\n getLongestLine(): number;\n\n /**\n * Returns the index of the glyph at the given position. This method requires\n * the layout method to have been called first.\n * @param x X coordinate of the position\n * @param y Y coordinate of the position\n */\n getGlyphPositionAtCoordinate(x: number, y: number): number;\n /**\n * Returns the bounding boxes of the glyphs in the given range. This method\n * requires the layout method to have been called first.\n * @param start Start index of the range\n * @param end End index of the range\n */\n getRectsForRange(start: number, end: number): SkRect[];\n /**\n * Returns the bounding boxes for all lines in the paragraph. This method\n * requires the layout method to have been called first.\n */\n getLineMetrics(): LineMetrics[];\n /**\n * Returns a list of rects with direction info for the placeholders added\n * to the paragraph.\n */\n getRectsForPlaceholders(): SkRectWithDirection[];\n}\n"],"mappings":"","ignoreList":[]}
@@ -1,5 +1,5 @@
1
1
  import type { CanvasKit, Paragraph } from "canvaskit-wasm";
2
- import type { SkRect, SkRectWithDirection, SkParagraph } from "../types";
2
+ import type { SkRect, SkRectWithDirection, SkParagraph, LineMetrics } from "../types";
3
3
  import { HostObject } from "./Host";
4
4
  import type { JsiSkCanvas } from "./JsiSkCanvas";
5
5
  export declare class JsiSkParagraph extends HostObject<Paragraph, "Paragraph"> implements SkParagraph {
@@ -14,6 +14,6 @@ export declare class JsiSkParagraph extends HostObject<Paragraph, "Paragraph"> i
14
14
  getGlyphPositionAtCoordinate(x: number, y: number): number;
15
15
  getRectsForPlaceholders(): SkRectWithDirection[];
16
16
  getRectsForRange(start: number, end: number): SkRect[];
17
- getLineMetrics(): SkRect[];
17
+ getLineMetrics(): LineMetrics[];
18
18
  dispose(): void;
19
19
  }
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.JsiSkParagraph = void 0;
7
7
  var _Host = require("./Host");
8
+ var _JsiSkRect = require("./JsiSkRect");
8
9
  class JsiSkParagraph extends _Host.HostObject {
9
10
  constructor(CanvasKit, ref) {
10
11
  super(CanvasKit, ref, "Paragraph");
@@ -38,12 +39,7 @@ class JsiSkParagraph extends _Host.HostObject {
38
39
  rect,
39
40
  dir
40
41
  }) => ({
41
- rect: {
42
- x: rect.at(0),
43
- y: rect.at(1),
44
- width: rect.at(2),
45
- height: rect.at(3)
46
- },
42
+ rect: new _JsiSkRect.JsiSkRect(this.CanvasKit, rect),
47
43
  direction: dir.value
48
44
  }));
49
45
  }
@@ -54,20 +50,10 @@ class JsiSkParagraph extends _Host.HostObject {
54
50
  value: 0
55
51
  } /** kTight */).map(({
56
52
  rect
57
- }) => ({
58
- x: rect[0],
59
- y: rect[1],
60
- width: rect[2],
61
- height: rect[3]
62
- }));
53
+ }) => new _JsiSkRect.JsiSkRect(this.CanvasKit, rect));
63
54
  }
64
55
  getLineMetrics() {
65
- return this.ref.getLineMetrics().map((r, index) => ({
66
- x: r.left,
67
- y: index * r.height,
68
- width: r.width,
69
- height: r.height
70
- }));
56
+ return this.ref.getLineMetrics();
71
57
  }
72
58
  dispose() {
73
59
  this.ref.delete();
@@ -1 +1 @@
1
- {"version":3,"names":["_Host","require","JsiSkParagraph","HostObject","constructor","CanvasKit","ref","getMinIntrinsicWidth","getMaxIntrinsicWidth","getLongestLine","layout","width","paint","canvas","x","y","drawParagraph","getHeight","getMaxWidth","getGlyphPositionAtCoordinate","pos","getRectsForPlaceholders","map","rect","dir","at","height","direction","value","getRectsForRange","start","end","getLineMetrics","r","index","left","dispose","delete","exports"],"sources":["JsiSkParagraph.ts"],"sourcesContent":["import type { CanvasKit, Paragraph } from \"canvaskit-wasm\";\n\nimport type { SkRect, SkRectWithDirection, SkParagraph } from \"../types\";\n\nimport { HostObject } from \"./Host\";\nimport type { JsiSkCanvas } from \"./JsiSkCanvas\";\n\nexport class JsiSkParagraph\n extends HostObject<Paragraph, \"Paragraph\">\n implements SkParagraph\n{\n constructor(CanvasKit: CanvasKit, ref: Paragraph) {\n super(CanvasKit, ref, \"Paragraph\");\n }\n getMinIntrinsicWidth(): number {\n return this.ref.getMinIntrinsicWidth();\n }\n\n getMaxIntrinsicWidth(): number {\n return this.ref.getMaxIntrinsicWidth();\n }\n\n getLongestLine(): number {\n return this.ref.getLongestLine();\n }\n\n layout(width: number): void {\n this.ref.layout(width);\n }\n paint(canvas: JsiSkCanvas, x: number, y: number): void {\n canvas.ref.drawParagraph(this.ref, x, y);\n }\n getHeight(): number {\n return this.ref.getHeight();\n }\n getMaxWidth(): number {\n return this.ref.getMaxWidth();\n }\n getGlyphPositionAtCoordinate(x: number, y: number): number {\n return this.ref.getGlyphPositionAtCoordinate(x, y).pos;\n }\n getRectsForPlaceholders(): SkRectWithDirection[] {\n return this.ref.getRectsForPlaceholders().map(({ rect, dir }) => ({\n rect: {\n x: rect.at(0)!,\n y: rect.at(1)!,\n width: rect.at(2)!,\n height: rect.at(3)!,\n },\n direction: dir.value,\n }));\n }\n getRectsForRange(start: number, end: number): SkRect[] {\n return this.ref\n .getRectsForRange(\n start,\n end,\n { value: 0 } /** kTight */,\n { value: 0 } /** kTight */\n )\n .map(({ rect }) => ({\n x: rect[0],\n y: rect[1],\n width: rect[2],\n height: rect[3],\n }));\n }\n getLineMetrics(): SkRect[] {\n return this.ref.getLineMetrics().map((r, index) => ({\n x: r.left,\n y: index * r.height,\n width: r.width,\n height: r.height,\n }));\n }\n\n dispose() {\n this.ref.delete();\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_Host","require","_JsiSkRect","JsiSkParagraph","HostObject","constructor","CanvasKit","ref","getMinIntrinsicWidth","getMaxIntrinsicWidth","getLongestLine","layout","width","paint","canvas","x","y","drawParagraph","getHeight","getMaxWidth","getGlyphPositionAtCoordinate","pos","getRectsForPlaceholders","map","rect","dir","JsiSkRect","direction","value","getRectsForRange","start","end","getLineMetrics","dispose","delete","exports"],"sources":["JsiSkParagraph.ts"],"sourcesContent":["import type { CanvasKit, Paragraph } from \"canvaskit-wasm\";\n\nimport type {\n SkRect,\n SkRectWithDirection,\n SkParagraph,\n LineMetrics,\n} from \"../types\";\n\nimport { HostObject } from \"./Host\";\nimport type { JsiSkCanvas } from \"./JsiSkCanvas\";\nimport { JsiSkRect } from \"./JsiSkRect\";\n\nexport class JsiSkParagraph\n extends HostObject<Paragraph, \"Paragraph\">\n implements SkParagraph\n{\n constructor(CanvasKit: CanvasKit, ref: Paragraph) {\n super(CanvasKit, ref, \"Paragraph\");\n }\n getMinIntrinsicWidth() {\n return this.ref.getMinIntrinsicWidth();\n }\n\n getMaxIntrinsicWidth() {\n return this.ref.getMaxIntrinsicWidth();\n }\n\n getLongestLine() {\n return this.ref.getLongestLine();\n }\n\n layout(width: number) {\n this.ref.layout(width);\n }\n paint(canvas: JsiSkCanvas, x: number, y: number) {\n canvas.ref.drawParagraph(this.ref, x, y);\n }\n getHeight() {\n return this.ref.getHeight();\n }\n getMaxWidth() {\n return this.ref.getMaxWidth();\n }\n getGlyphPositionAtCoordinate(x: number, y: number) {\n return this.ref.getGlyphPositionAtCoordinate(x, y).pos;\n }\n getRectsForPlaceholders(): SkRectWithDirection[] {\n return this.ref.getRectsForPlaceholders().map(({ rect, dir }) => ({\n rect: new JsiSkRect(this.CanvasKit, rect),\n direction: dir.value,\n }));\n }\n getRectsForRange(start: number, end: number): SkRect[] {\n return this.ref\n .getRectsForRange(\n start,\n end,\n { value: 0 } /** kTight */,\n { value: 0 } /** kTight */\n )\n .map(({ rect }) => new JsiSkRect(this.CanvasKit, rect));\n }\n getLineMetrics(): LineMetrics[] {\n return this.ref.getLineMetrics();\n }\n\n dispose() {\n this.ref.delete();\n }\n}\n"],"mappings":";;;;;;AASA,IAAAA,KAAA,GAAAC,OAAA;AAEA,IAAAC,UAAA,GAAAD,OAAA;AAEO,MAAME,cAAc,SACjBC,gBAAU,CAEpB;EACEC,WAAWA,CAACC,SAAoB,EAAEC,GAAc,EAAE;IAChD,KAAK,CAACD,SAAS,EAAEC,GAAG,EAAE,WAAW,CAAC;EACpC;EACAC,oBAAoBA,CAAA,EAAG;IACrB,OAAO,IAAI,CAACD,GAAG,CAACC,oBAAoB,CAAC,CAAC;EACxC;EAEAC,oBAAoBA,CAAA,EAAG;IACrB,OAAO,IAAI,CAACF,GAAG,CAACE,oBAAoB,CAAC,CAAC;EACxC;EAEAC,cAAcA,CAAA,EAAG;IACf,OAAO,IAAI,CAACH,GAAG,CAACG,cAAc,CAAC,CAAC;EAClC;EAEAC,MAAMA,CAACC,KAAa,EAAE;IACpB,IAAI,CAACL,GAAG,CAACI,MAAM,CAACC,KAAK,CAAC;EACxB;EACAC,KAAKA,CAACC,MAAmB,EAAEC,CAAS,EAAEC,CAAS,EAAE;IAC/CF,MAAM,CAACP,GAAG,CAACU,aAAa,CAAC,IAAI,CAACV,GAAG,EAAEQ,CAAC,EAAEC,CAAC,CAAC;EAC1C;EACAE,SAASA,CAAA,EAAG;IACV,OAAO,IAAI,CAACX,GAAG,CAACW,SAAS,CAAC,CAAC;EAC7B;EACAC,WAAWA,CAAA,EAAG;IACZ,OAAO,IAAI,CAACZ,GAAG,CAACY,WAAW,CAAC,CAAC;EAC/B;EACAC,4BAA4BA,CAACL,CAAS,EAAEC,CAAS,EAAE;IACjD,OAAO,IAAI,CAACT,GAAG,CAACa,4BAA4B,CAACL,CAAC,EAAEC,CAAC,CAAC,CAACK,GAAG;EACxD;EACAC,uBAAuBA,CAAA,EAA0B;IAC/C,OAAO,IAAI,CAACf,GAAG,CAACe,uBAAuB,CAAC,CAAC,CAACC,GAAG,CAAC,CAAC;MAAEC,IAAI;MAAEC;IAAI,CAAC,MAAM;MAChED,IAAI,EAAE,IAAIE,oBAAS,CAAC,IAAI,CAACpB,SAAS,EAAEkB,IAAI,CAAC;MACzCG,SAAS,EAAEF,GAAG,CAACG;IACjB,CAAC,CAAC,CAAC;EACL;EACAC,gBAAgBA,CAACC,KAAa,EAAEC,GAAW,EAAY;IACrD,OAAO,IAAI,CAACxB,GAAG,CACZsB,gBAAgB,CACfC,KAAK,EACLC,GAAG,EACH;MAAEH,KAAK,EAAE;IAAE,CAAC,CAAC,eACb;MAAEA,KAAK,EAAE;IAAE,CAAC,CAAC,aACf,CAAC,CACAL,GAAG,CAAC,CAAC;MAAEC;IAAK,CAAC,KAAK,IAAIE,oBAAS,CAAC,IAAI,CAACpB,SAAS,EAAEkB,IAAI,CAAC,CAAC;EAC3D;EACAQ,cAAcA,CAAA,EAAkB;IAC9B,OAAO,IAAI,CAACzB,GAAG,CAACyB,cAAc,CAAC,CAAC;EAClC;EAEAC,OAAOA,CAAA,EAAG;IACR,IAAI,CAAC1B,GAAG,CAAC2B,MAAM,CAAC,CAAC;EACnB;AACF;AAACC,OAAA,CAAAhC,cAAA,GAAAA,cAAA","ignoreList":[]}
@@ -12,7 +12,7 @@ export declare class ParagraphAsset<Ctx extends EvalContext> extends SkiaObject<
12
12
  getLongestLine(): number;
13
13
  getGlyphPositionAtCoordinate(x: number, y: number): number;
14
14
  getRectsForRange(start: number, end: number): import("../../../../skia/types").SkRect[];
15
- getLineMetrics(): import("../../../../skia/types").SkRect[];
15
+ getLineMetrics(): import("../../../../skia/types").LineMetrics[];
16
16
  getRectsForPlaceholders(): import("../../../../skia/types").SkRectWithDirection[];
17
17
  __typename__: "Paragraph";
18
18
  dispose(): void;
@@ -2,6 +2,36 @@ import type { SkCanvas } from "../Canvas";
2
2
  import type { SkJSIInstance } from "../JsiInstance";
3
3
  import type { SkRect } from "../Rect";
4
4
  import type { TextDirection } from "./ParagraphStyle";
5
+ export interface LineMetrics {
6
+ /** The index in the text buffer the line begins. */
7
+ startIndex: number;
8
+ /** The index in the text buffer the line ends. */
9
+ endIndex: number;
10
+ endExcludingWhitespaces: number;
11
+ endIncludingNewline: number;
12
+ /** True if the line ends in a hard break (e.g. newline) */
13
+ isHardBreak: boolean;
14
+ /**
15
+ * The final computed ascent for the line. This can be impacted by
16
+ * the strut, height, scaling, as well as outlying runs that are very tall.
17
+ */
18
+ ascent: number;
19
+ /**
20
+ * The final computed descent for the line. This can be impacted by
21
+ * the strut, height, scaling, as well as outlying runs that are very tall.
22
+ */
23
+ descent: number;
24
+ /** round(ascent + descent) */
25
+ height: number;
26
+ /** width of the line */
27
+ width: number;
28
+ /** The left edge of the line. The right edge can be obtained with `left + width` */
29
+ left: number;
30
+ /** The y position of the baseline for this line from the top of the paragraph. */
31
+ baseline: number;
32
+ /** Zero indexed line number. */
33
+ lineNumber: number;
34
+ }
5
35
  export interface SkRectWithDirection {
6
36
  rect: SkRect;
7
37
  direction: TextDirection;
@@ -70,7 +100,7 @@ export interface SkParagraph extends SkJSIInstance<"Paragraph"> {
70
100
  * Returns the bounding boxes for all lines in the paragraph. This method
71
101
  * requires the layout method to have been called first.
72
102
  */
73
- getLineMetrics(): Array<SkRect>;
103
+ getLineMetrics(): LineMetrics[];
74
104
  /**
75
105
  * Returns a list of rects with direction info for the placeholders added
76
106
  * to the paragraph.
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["Paragraph.ts"],"sourcesContent":["import type { SkCanvas } from \"../Canvas\";\nimport type { SkJSIInstance } from \"../JsiInstance\";\nimport type { SkRect } from \"../Rect\";\n\nimport type { TextDirection } from \"./ParagraphStyle\";\n\nexport interface SkRectWithDirection {\n rect: SkRect;\n direction: TextDirection;\n}\n\nexport interface SkParagraph extends SkJSIInstance<\"Paragraph\"> {\n /**\n * Calculates the position of the the glyphs in the paragraph\n * @param width Max width of the paragraph\n */\n layout(width: number): void;\n /**\n * Paints the paragraph to the provded canvas\n * @param canvas Canvas to paint into\n * @param x X coordinate to paint at\n * @param y Y coordinate to paint at\n */\n paint(canvas: SkCanvas, x: number, y: number): void;\n /**\n * Returns the height of the paragraph. This method requires the layout\n * method to have been called first.\n */\n getHeight(): number;\n /**\n * Returns the max width of the paragraph. This method requires the layout\n * method to have been called first.\n */\n getMaxWidth(): number;\n /**\n * Returns the minimum intrinsic width of the paragraph.\n * The minimum intrinsic width is the width beyond which increasing the width of the paragraph\n * does not decrease the height. This is effectively the width at which the paragraph\n * can no longer wrap lines and is forced to overflow.\n * This method requires the layout method to have been called first.\n * @returns {number} The minimum intrinsic width of the paragraph.\n */\n getMinIntrinsicWidth(): number;\n /**\n * Returns the maximum intrinsic width of the paragraph.\n * The maximum intrinsic width is the width at which the paragraph can layout its content without line breaks,\n * meaning it's the width of the widest line or the widest word if the widest line is shorter than that.\n * This width represents the ideal width for the paragraph to display all content in a single line without overflow.\n * This method requires the layout method to have been called first.\n * @returns {number} The maximum intrinsic width of the paragraph.\n */\n getMaxIntrinsicWidth(): number;\n\n /**\n * Returns the width of the longest line in the paragraph.\n * This method requires the layout method to have been called first.\n */\n getLongestLine(): number;\n\n /**\n * Returns the index of the glyph at the given position. This method requires\n * the layout method to have been called first.\n * @param x X coordinate of the position\n * @param y Y coordinate of the position\n */\n getGlyphPositionAtCoordinate(x: number, y: number): number;\n /**\n * Returns the bounding boxes of the glyphs in the given range. This method\n * requires the layout method to have been called first.\n * @param start Start index of the range\n * @param end End index of the range\n */\n getRectsForRange(start: number, end: number): SkRect[];\n /**\n * Returns the bounding boxes for all lines in the paragraph. This method\n * requires the layout method to have been called first.\n */\n getLineMetrics(): Array<SkRect>;\n /**\n * Returns a list of rects with direction info for the placeholders added\n * to the paragraph.\n */\n getRectsForPlaceholders(): SkRectWithDirection[];\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["Paragraph.ts"],"sourcesContent":["import type { SkCanvas } from \"../Canvas\";\nimport type { SkJSIInstance } from \"../JsiInstance\";\nimport type { SkRect } from \"../Rect\";\n\nimport type { TextDirection } from \"./ParagraphStyle\";\n\nexport interface LineMetrics {\n /** The index in the text buffer the line begins. */\n startIndex: number;\n /** The index in the text buffer the line ends. */\n endIndex: number;\n endExcludingWhitespaces: number;\n endIncludingNewline: number;\n /** True if the line ends in a hard break (e.g. newline) */\n isHardBreak: boolean;\n /**\n * The final computed ascent for the line. This can be impacted by\n * the strut, height, scaling, as well as outlying runs that are very tall.\n */\n ascent: number;\n /**\n * The final computed descent for the line. This can be impacted by\n * the strut, height, scaling, as well as outlying runs that are very tall.\n */\n descent: number;\n /** round(ascent + descent) */\n height: number;\n /** width of the line */\n width: number;\n /** The left edge of the line. The right edge can be obtained with `left + width` */\n left: number;\n /** The y position of the baseline for this line from the top of the paragraph. */\n baseline: number;\n /** Zero indexed line number. */\n lineNumber: number;\n}\n\nexport interface SkRectWithDirection {\n rect: SkRect;\n direction: TextDirection;\n}\n\nexport interface SkParagraph extends SkJSIInstance<\"Paragraph\"> {\n /**\n * Calculates the position of the the glyphs in the paragraph\n * @param width Max width of the paragraph\n */\n layout(width: number): void;\n /**\n * Paints the paragraph to the provded canvas\n * @param canvas Canvas to paint into\n * @param x X coordinate to paint at\n * @param y Y coordinate to paint at\n */\n paint(canvas: SkCanvas, x: number, y: number): void;\n /**\n * Returns the height of the paragraph. This method requires the layout\n * method to have been called first.\n */\n getHeight(): number;\n /**\n * Returns the max width of the paragraph. This method requires the layout\n * method to have been called first.\n */\n getMaxWidth(): number;\n /**\n * Returns the minimum intrinsic width of the paragraph.\n * The minimum intrinsic width is the width beyond which increasing the width of the paragraph\n * does not decrease the height. This is effectively the width at which the paragraph\n * can no longer wrap lines and is forced to overflow.\n * This method requires the layout method to have been called first.\n * @returns {number} The minimum intrinsic width of the paragraph.\n */\n getMinIntrinsicWidth(): number;\n /**\n * Returns the maximum intrinsic width of the paragraph.\n * The maximum intrinsic width is the width at which the paragraph can layout its content without line breaks,\n * meaning it's the width of the widest line or the widest word if the widest line is shorter than that.\n * This width represents the ideal width for the paragraph to display all content in a single line without overflow.\n * This method requires the layout method to have been called first.\n * @returns {number} The maximum intrinsic width of the paragraph.\n */\n getMaxIntrinsicWidth(): number;\n\n /**\n * Returns the width of the longest line in the paragraph.\n * This method requires the layout method to have been called first.\n */\n getLongestLine(): number;\n\n /**\n * Returns the index of the glyph at the given position. This method requires\n * the layout method to have been called first.\n * @param x X coordinate of the position\n * @param y Y coordinate of the position\n */\n getGlyphPositionAtCoordinate(x: number, y: number): number;\n /**\n * Returns the bounding boxes of the glyphs in the given range. This method\n * requires the layout method to have been called first.\n * @param start Start index of the range\n * @param end End index of the range\n */\n getRectsForRange(start: number, end: number): SkRect[];\n /**\n * Returns the bounding boxes for all lines in the paragraph. This method\n * requires the layout method to have been called first.\n */\n getLineMetrics(): LineMetrics[];\n /**\n * Returns a list of rects with direction info for the placeholders added\n * to the paragraph.\n */\n getRectsForPlaceholders(): SkRectWithDirection[];\n}\n"],"mappings":"","ignoreList":[]}
@@ -1,5 +1,5 @@
1
1
  import type { CanvasKit, Paragraph } from "canvaskit-wasm";
2
- import type { SkRect, SkRectWithDirection, SkParagraph } from "../types";
2
+ import type { SkRect, SkRectWithDirection, SkParagraph, LineMetrics } from "../types";
3
3
  import { HostObject } from "./Host";
4
4
  import type { JsiSkCanvas } from "./JsiSkCanvas";
5
5
  export declare class JsiSkParagraph extends HostObject<Paragraph, "Paragraph"> implements SkParagraph {
@@ -14,6 +14,6 @@ export declare class JsiSkParagraph extends HostObject<Paragraph, "Paragraph"> i
14
14
  getGlyphPositionAtCoordinate(x: number, y: number): number;
15
15
  getRectsForPlaceholders(): SkRectWithDirection[];
16
16
  getRectsForRange(start: number, end: number): SkRect[];
17
- getLineMetrics(): SkRect[];
17
+ getLineMetrics(): LineMetrics[];
18
18
  dispose(): void;
19
19
  }
@@ -1,4 +1,5 @@
1
1
  import { HostObject } from "./Host";
2
+ import { JsiSkRect } from "./JsiSkRect";
2
3
  export class JsiSkParagraph extends HostObject {
3
4
  constructor(CanvasKit, ref) {
4
5
  super(CanvasKit, ref, "Paragraph");
@@ -32,12 +33,7 @@ export class JsiSkParagraph extends HostObject {
32
33
  rect,
33
34
  dir
34
35
  }) => ({
35
- rect: {
36
- x: rect.at(0),
37
- y: rect.at(1),
38
- width: rect.at(2),
39
- height: rect.at(3)
40
- },
36
+ rect: new JsiSkRect(this.CanvasKit, rect),
41
37
  direction: dir.value
42
38
  }));
43
39
  }
@@ -48,20 +44,10 @@ export class JsiSkParagraph extends HostObject {
48
44
  value: 0
49
45
  } /** kTight */).map(({
50
46
  rect
51
- }) => ({
52
- x: rect[0],
53
- y: rect[1],
54
- width: rect[2],
55
- height: rect[3]
56
- }));
47
+ }) => new JsiSkRect(this.CanvasKit, rect));
57
48
  }
58
49
  getLineMetrics() {
59
- return this.ref.getLineMetrics().map((r, index) => ({
60
- x: r.left,
61
- y: index * r.height,
62
- width: r.width,
63
- height: r.height
64
- }));
50
+ return this.ref.getLineMetrics();
65
51
  }
66
52
  dispose() {
67
53
  this.ref.delete();
@@ -1 +1 @@
1
- {"version":3,"names":["HostObject","JsiSkParagraph","constructor","CanvasKit","ref","getMinIntrinsicWidth","getMaxIntrinsicWidth","getLongestLine","layout","width","paint","canvas","x","y","drawParagraph","getHeight","getMaxWidth","getGlyphPositionAtCoordinate","pos","getRectsForPlaceholders","map","rect","dir","at","height","direction","value","getRectsForRange","start","end","getLineMetrics","r","index","left","dispose","delete"],"sources":["JsiSkParagraph.ts"],"sourcesContent":["import type { CanvasKit, Paragraph } from \"canvaskit-wasm\";\n\nimport type { SkRect, SkRectWithDirection, SkParagraph } from \"../types\";\n\nimport { HostObject } from \"./Host\";\nimport type { JsiSkCanvas } from \"./JsiSkCanvas\";\n\nexport class JsiSkParagraph\n extends HostObject<Paragraph, \"Paragraph\">\n implements SkParagraph\n{\n constructor(CanvasKit: CanvasKit, ref: Paragraph) {\n super(CanvasKit, ref, \"Paragraph\");\n }\n getMinIntrinsicWidth(): number {\n return this.ref.getMinIntrinsicWidth();\n }\n\n getMaxIntrinsicWidth(): number {\n return this.ref.getMaxIntrinsicWidth();\n }\n\n getLongestLine(): number {\n return this.ref.getLongestLine();\n }\n\n layout(width: number): void {\n this.ref.layout(width);\n }\n paint(canvas: JsiSkCanvas, x: number, y: number): void {\n canvas.ref.drawParagraph(this.ref, x, y);\n }\n getHeight(): number {\n return this.ref.getHeight();\n }\n getMaxWidth(): number {\n return this.ref.getMaxWidth();\n }\n getGlyphPositionAtCoordinate(x: number, y: number): number {\n return this.ref.getGlyphPositionAtCoordinate(x, y).pos;\n }\n getRectsForPlaceholders(): SkRectWithDirection[] {\n return this.ref.getRectsForPlaceholders().map(({ rect, dir }) => ({\n rect: {\n x: rect.at(0)!,\n y: rect.at(1)!,\n width: rect.at(2)!,\n height: rect.at(3)!,\n },\n direction: dir.value,\n }));\n }\n getRectsForRange(start: number, end: number): SkRect[] {\n return this.ref\n .getRectsForRange(\n start,\n end,\n { value: 0 } /** kTight */,\n { value: 0 } /** kTight */\n )\n .map(({ rect }) => ({\n x: rect[0],\n y: rect[1],\n width: rect[2],\n height: rect[3],\n }));\n }\n getLineMetrics(): SkRect[] {\n return this.ref.getLineMetrics().map((r, index) => ({\n x: r.left,\n y: index * r.height,\n width: r.width,\n height: r.height,\n }));\n }\n\n dispose() {\n this.ref.delete();\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["HostObject","JsiSkRect","JsiSkParagraph","constructor","CanvasKit","ref","getMinIntrinsicWidth","getMaxIntrinsicWidth","getLongestLine","layout","width","paint","canvas","x","y","drawParagraph","getHeight","getMaxWidth","getGlyphPositionAtCoordinate","pos","getRectsForPlaceholders","map","rect","dir","direction","value","getRectsForRange","start","end","getLineMetrics","dispose","delete"],"sources":["JsiSkParagraph.ts"],"sourcesContent":["import type { CanvasKit, Paragraph } from \"canvaskit-wasm\";\n\nimport type {\n SkRect,\n SkRectWithDirection,\n SkParagraph,\n LineMetrics,\n} from \"../types\";\n\nimport { HostObject } from \"./Host\";\nimport type { JsiSkCanvas } from \"./JsiSkCanvas\";\nimport { JsiSkRect } from \"./JsiSkRect\";\n\nexport class JsiSkParagraph\n extends HostObject<Paragraph, \"Paragraph\">\n implements SkParagraph\n{\n constructor(CanvasKit: CanvasKit, ref: Paragraph) {\n super(CanvasKit, ref, \"Paragraph\");\n }\n getMinIntrinsicWidth() {\n return this.ref.getMinIntrinsicWidth();\n }\n\n getMaxIntrinsicWidth() {\n return this.ref.getMaxIntrinsicWidth();\n }\n\n getLongestLine() {\n return this.ref.getLongestLine();\n }\n\n layout(width: number) {\n this.ref.layout(width);\n }\n paint(canvas: JsiSkCanvas, x: number, y: number) {\n canvas.ref.drawParagraph(this.ref, x, y);\n }\n getHeight() {\n return this.ref.getHeight();\n }\n getMaxWidth() {\n return this.ref.getMaxWidth();\n }\n getGlyphPositionAtCoordinate(x: number, y: number) {\n return this.ref.getGlyphPositionAtCoordinate(x, y).pos;\n }\n getRectsForPlaceholders(): SkRectWithDirection[] {\n return this.ref.getRectsForPlaceholders().map(({ rect, dir }) => ({\n rect: new JsiSkRect(this.CanvasKit, rect),\n direction: dir.value,\n }));\n }\n getRectsForRange(start: number, end: number): SkRect[] {\n return this.ref\n .getRectsForRange(\n start,\n end,\n { value: 0 } /** kTight */,\n { value: 0 } /** kTight */\n )\n .map(({ rect }) => new JsiSkRect(this.CanvasKit, rect));\n }\n getLineMetrics(): LineMetrics[] {\n return this.ref.getLineMetrics();\n }\n\n dispose() {\n this.ref.delete();\n }\n}\n"],"mappings":"AASA,SAASA,UAAU,QAAQ,QAAQ;AAEnC,SAASC,SAAS,QAAQ,aAAa;AAEvC,OAAO,MAAMC,cAAc,SACjBF,UAAU,CAEpB;EACEG,WAAWA,CAACC,SAAoB,EAAEC,GAAc,EAAE;IAChD,KAAK,CAACD,SAAS,EAAEC,GAAG,EAAE,WAAW,CAAC;EACpC;EACAC,oBAAoBA,CAAA,EAAG;IACrB,OAAO,IAAI,CAACD,GAAG,CAACC,oBAAoB,CAAC,CAAC;EACxC;EAEAC,oBAAoBA,CAAA,EAAG;IACrB,OAAO,IAAI,CAACF,GAAG,CAACE,oBAAoB,CAAC,CAAC;EACxC;EAEAC,cAAcA,CAAA,EAAG;IACf,OAAO,IAAI,CAACH,GAAG,CAACG,cAAc,CAAC,CAAC;EAClC;EAEAC,MAAMA,CAACC,KAAa,EAAE;IACpB,IAAI,CAACL,GAAG,CAACI,MAAM,CAACC,KAAK,CAAC;EACxB;EACAC,KAAKA,CAACC,MAAmB,EAAEC,CAAS,EAAEC,CAAS,EAAE;IAC/CF,MAAM,CAACP,GAAG,CAACU,aAAa,CAAC,IAAI,CAACV,GAAG,EAAEQ,CAAC,EAAEC,CAAC,CAAC;EAC1C;EACAE,SAASA,CAAA,EAAG;IACV,OAAO,IAAI,CAACX,GAAG,CAACW,SAAS,CAAC,CAAC;EAC7B;EACAC,WAAWA,CAAA,EAAG;IACZ,OAAO,IAAI,CAACZ,GAAG,CAACY,WAAW,CAAC,CAAC;EAC/B;EACAC,4BAA4BA,CAACL,CAAS,EAAEC,CAAS,EAAE;IACjD,OAAO,IAAI,CAACT,GAAG,CAACa,4BAA4B,CAACL,CAAC,EAAEC,CAAC,CAAC,CAACK,GAAG;EACxD;EACAC,uBAAuBA,CAAA,EAA0B;IAC/C,OAAO,IAAI,CAACf,GAAG,CAACe,uBAAuB,CAAC,CAAC,CAACC,GAAG,CAAC,CAAC;MAAEC,IAAI;MAAEC;IAAI,CAAC,MAAM;MAChED,IAAI,EAAE,IAAIrB,SAAS,CAAC,IAAI,CAACG,SAAS,EAAEkB,IAAI,CAAC;MACzCE,SAAS,EAAED,GAAG,CAACE;IACjB,CAAC,CAAC,CAAC;EACL;EACAC,gBAAgBA,CAACC,KAAa,EAAEC,GAAW,EAAY;IACrD,OAAO,IAAI,CAACvB,GAAG,CACZqB,gBAAgB,CACfC,KAAK,EACLC,GAAG,EACH;MAAEH,KAAK,EAAE;IAAE,CAAC,CAAC,eACb;MAAEA,KAAK,EAAE;IAAE,CAAC,CAAC,aACf,CAAC,CACAJ,GAAG,CAAC,CAAC;MAAEC;IAAK,CAAC,KAAK,IAAIrB,SAAS,CAAC,IAAI,CAACG,SAAS,EAAEkB,IAAI,CAAC,CAAC;EAC3D;EACAO,cAAcA,CAAA,EAAkB;IAC9B,OAAO,IAAI,CAACxB,GAAG,CAACwB,cAAc,CAAC,CAAC;EAClC;EAEAC,OAAOA,CAAA,EAAG;IACR,IAAI,CAACzB,GAAG,CAAC0B,MAAM,CAAC,CAAC;EACnB;AACF","ignoreList":[]}
@@ -12,7 +12,7 @@ export declare class ParagraphAsset<Ctx extends EvalContext> extends SkiaObject<
12
12
  getLongestLine(): number;
13
13
  getGlyphPositionAtCoordinate(x: number, y: number): number;
14
14
  getRectsForRange(start: number, end: number): import("../../../../skia/types").SkRect[];
15
- getLineMetrics(): import("../../../../skia/types").SkRect[];
15
+ getLineMetrics(): import("../../../../skia/types").LineMetrics[];
16
16
  getRectsForPlaceholders(): import("../../../../skia/types").SkRectWithDirection[];
17
17
  __typename__: "Paragraph";
18
18
  dispose(): void;
@@ -2,6 +2,36 @@ import type { SkCanvas } from "../Canvas";
2
2
  import type { SkJSIInstance } from "../JsiInstance";
3
3
  import type { SkRect } from "../Rect";
4
4
  import type { TextDirection } from "./ParagraphStyle";
5
+ export interface LineMetrics {
6
+ /** The index in the text buffer the line begins. */
7
+ startIndex: number;
8
+ /** The index in the text buffer the line ends. */
9
+ endIndex: number;
10
+ endExcludingWhitespaces: number;
11
+ endIncludingNewline: number;
12
+ /** True if the line ends in a hard break (e.g. newline) */
13
+ isHardBreak: boolean;
14
+ /**
15
+ * The final computed ascent for the line. This can be impacted by
16
+ * the strut, height, scaling, as well as outlying runs that are very tall.
17
+ */
18
+ ascent: number;
19
+ /**
20
+ * The final computed descent for the line. This can be impacted by
21
+ * the strut, height, scaling, as well as outlying runs that are very tall.
22
+ */
23
+ descent: number;
24
+ /** round(ascent + descent) */
25
+ height: number;
26
+ /** width of the line */
27
+ width: number;
28
+ /** The left edge of the line. The right edge can be obtained with `left + width` */
29
+ left: number;
30
+ /** The y position of the baseline for this line from the top of the paragraph. */
31
+ baseline: number;
32
+ /** Zero indexed line number. */
33
+ lineNumber: number;
34
+ }
5
35
  export interface SkRectWithDirection {
6
36
  rect: SkRect;
7
37
  direction: TextDirection;
@@ -70,7 +100,7 @@ export interface SkParagraph extends SkJSIInstance<"Paragraph"> {
70
100
  * Returns the bounding boxes for all lines in the paragraph. This method
71
101
  * requires the layout method to have been called first.
72
102
  */
73
- getLineMetrics(): Array<SkRect>;
103
+ getLineMetrics(): LineMetrics[];
74
104
  /**
75
105
  * Returns a list of rects with direction info for the placeholders added
76
106
  * to the paragraph.
@@ -1,5 +1,5 @@
1
1
  import type { CanvasKit, Paragraph } from "canvaskit-wasm";
2
- import type { SkRect, SkRectWithDirection, SkParagraph } from "../types";
2
+ import type { SkRect, SkRectWithDirection, SkParagraph, LineMetrics } from "../types";
3
3
  import { HostObject } from "./Host";
4
4
  import type { JsiSkCanvas } from "./JsiSkCanvas";
5
5
  export declare class JsiSkParagraph extends HostObject<Paragraph, "Paragraph"> implements SkParagraph {
@@ -14,6 +14,6 @@ export declare class JsiSkParagraph extends HostObject<Paragraph, "Paragraph"> i
14
14
  getGlyphPositionAtCoordinate(x: number, y: number): number;
15
15
  getRectsForPlaceholders(): SkRectWithDirection[];
16
16
  getRectsForRange(start: number, end: number): SkRect[];
17
- getLineMetrics(): SkRect[];
17
+ getLineMetrics(): LineMetrics[];
18
18
  dispose(): void;
19
19
  }
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "setup-skia-web": "scripts/setup-canvaskit.js"
9
9
  },
10
10
  "title": "React Native Skia",
11
- "version": "2.2.8",
11
+ "version": "2.2.9",
12
12
  "description": "High-performance React Native Graphics using Skia",
13
13
  "main": "lib/module/index.js",
14
14
  "react-native": "src/index.ts",
@@ -0,0 +1,383 @@
1
+ import { resolveFile, surface } from "../setup";
2
+ import {
3
+ PlaceholderAlignment,
4
+ TextBaseline,
5
+ TextDirection,
6
+ } from "../../../skia/types";
7
+
8
+ const RobotoRegular = Array.from(
9
+ resolveFile("skia/__tests__/assets/Roboto-Regular.ttf")
10
+ );
11
+
12
+ describe("Paragraph Methods", () => {
13
+ describe("getRectsForPlaceholders", () => {
14
+ it("should handle multiple placeholders with different alignments", async () => {
15
+ const placeholderRects = await surface.eval(
16
+ (Skia, ctx) => {
17
+ const robotoRegular = Skia.Typeface.MakeFreeTypeFaceFromData(
18
+ Skia.Data.fromBytes(new Uint8Array(ctx.RobotoRegular))
19
+ )!;
20
+ const provider = Skia.TypefaceFontProvider.Make();
21
+ provider.registerFont(robotoRegular, "Roboto");
22
+
23
+ const builder = Skia.ParagraphBuilder.Make(
24
+ {
25
+ textStyle: {
26
+ color: Skia.Color("black"),
27
+ fontFamilies: ["Roboto"],
28
+ fontSize: 16,
29
+ },
30
+ },
31
+ provider
32
+ );
33
+
34
+ builder.addText("Start ");
35
+ builder.addPlaceholder(
36
+ 20,
37
+ 20,
38
+ ctx.PlaceholderAlignment.Baseline,
39
+ ctx.TextBaseline.Alphabetic
40
+ );
41
+ builder.addText(" middle ");
42
+ builder.addPlaceholder(
43
+ 15,
44
+ 15,
45
+ ctx.PlaceholderAlignment.Top,
46
+ ctx.TextBaseline.Alphabetic
47
+ );
48
+ builder.addText(" end");
49
+
50
+ const paragraph = builder.build();
51
+ paragraph.layout(200);
52
+
53
+ const rects = paragraph.getRectsForPlaceholders();
54
+ return rects.map((r) => ({
55
+ x: r.rect.x,
56
+ y: r.rect.y,
57
+ width: r.rect.width,
58
+ height: r.rect.height,
59
+ direction: r.direction,
60
+ }));
61
+ },
62
+ {
63
+ RobotoRegular,
64
+ PlaceholderAlignment,
65
+ TextBaseline,
66
+ }
67
+ );
68
+
69
+ expect(placeholderRects).toHaveLength(2);
70
+ expect(placeholderRects[0].width).toBe(20);
71
+ expect(placeholderRects[0].height).toBe(20);
72
+ expect(placeholderRects[1].width).toBeCloseTo(15);
73
+ expect(placeholderRects[1].height).toBeCloseTo(15);
74
+ });
75
+
76
+ it("should return correct direction for placeholders", async () => {
77
+ const placeholderInfo = await surface.eval(
78
+ (Skia, ctx) => {
79
+ const robotoRegular = Skia.Typeface.MakeFreeTypeFaceFromData(
80
+ Skia.Data.fromBytes(new Uint8Array(ctx.RobotoRegular))
81
+ )!;
82
+ const provider = Skia.TypefaceFontProvider.Make();
83
+ provider.registerFont(robotoRegular, "Roboto");
84
+
85
+ const builder = Skia.ParagraphBuilder.Make(
86
+ {
87
+ textStyle: {
88
+ color: Skia.Color("black"),
89
+ fontFamilies: ["Roboto"],
90
+ fontSize: 16,
91
+ },
92
+ },
93
+ provider
94
+ );
95
+
96
+ builder.addText("Text with ");
97
+ builder.addPlaceholder(30, 30);
98
+ builder.addText(" placeholder");
99
+
100
+ const paragraph = builder.build();
101
+ paragraph.layout(300);
102
+
103
+ const rects = paragraph.getRectsForPlaceholders();
104
+ return rects.map((r) => ({
105
+ direction: r.direction === ctx.TextDirection.LTR ? "LTR" : "RTL",
106
+ }));
107
+ },
108
+ {
109
+ RobotoRegular,
110
+ TextDirection,
111
+ }
112
+ );
113
+
114
+ expect(placeholderInfo).toHaveLength(1);
115
+ expect(placeholderInfo[0].direction).toBe("LTR");
116
+ });
117
+
118
+ it("should return empty array when no placeholders", async () => {
119
+ const placeholderCount = await surface.eval(
120
+ (Skia, ctx) => {
121
+ const robotoRegular = Skia.Typeface.MakeFreeTypeFaceFromData(
122
+ Skia.Data.fromBytes(new Uint8Array(ctx.RobotoRegular))
123
+ )!;
124
+ const provider = Skia.TypefaceFontProvider.Make();
125
+ provider.registerFont(robotoRegular, "Roboto");
126
+
127
+ const builder = Skia.ParagraphBuilder.Make(
128
+ {
129
+ textStyle: {
130
+ color: Skia.Color("black"),
131
+ fontFamilies: ["Roboto"],
132
+ fontSize: 16,
133
+ },
134
+ },
135
+ provider
136
+ );
137
+
138
+ builder.addText("Text without any placeholders");
139
+
140
+ const paragraph = builder.build();
141
+ paragraph.layout(300);
142
+
143
+ const rects = paragraph.getRectsForPlaceholders();
144
+ return rects.length;
145
+ },
146
+ {
147
+ RobotoRegular,
148
+ }
149
+ );
150
+
151
+ expect(placeholderCount).toBe(0);
152
+ });
153
+ });
154
+
155
+ describe("getLineMetrics", () => {
156
+ it("should return line metrics for single line text", async () => {
157
+ const lineMetrics = await surface.eval(
158
+ (Skia, ctx) => {
159
+ const robotoRegular = Skia.Typeface.MakeFreeTypeFaceFromData(
160
+ Skia.Data.fromBytes(new Uint8Array(ctx.RobotoRegular))
161
+ )!;
162
+ const provider = Skia.TypefaceFontProvider.Make();
163
+ provider.registerFont(robotoRegular, "Roboto");
164
+
165
+ const builder = Skia.ParagraphBuilder.Make(
166
+ {
167
+ textStyle: {
168
+ color: Skia.Color("black"),
169
+ fontFamilies: ["Roboto"],
170
+ fontSize: 16,
171
+ },
172
+ },
173
+ provider
174
+ );
175
+
176
+ builder.addText("Single line text");
177
+
178
+ const paragraph = builder.build();
179
+ paragraph.layout(300);
180
+
181
+ return paragraph.getLineMetrics();
182
+ },
183
+ {
184
+ RobotoRegular,
185
+ }
186
+ );
187
+
188
+ expect(lineMetrics).toHaveLength(1);
189
+ expect(lineMetrics[0].lineNumber).toBe(0);
190
+ expect(lineMetrics[0].startIndex).toBe(0);
191
+ expect(lineMetrics[0].endIndex).toBe(16);
192
+ expect(lineMetrics[0].width).toBeGreaterThan(0);
193
+ expect(lineMetrics[0].height).toBeGreaterThan(0);
194
+ expect(lineMetrics[0].ascent).toBeGreaterThan(0);
195
+ expect(lineMetrics[0].descent).toBeGreaterThan(0);
196
+ // Note: Even single lines without explicit breaks may report isHardBreak as true
197
+ expect(typeof lineMetrics[0].isHardBreak).toBe('boolean');
198
+ });
199
+
200
+ it("should return line metrics for multi-line text with wrapping", async () => {
201
+ const lineMetrics = await surface.eval(
202
+ (Skia, ctx) => {
203
+ const robotoRegular = Skia.Typeface.MakeFreeTypeFaceFromData(
204
+ Skia.Data.fromBytes(new Uint8Array(ctx.RobotoRegular))
205
+ )!;
206
+ const provider = Skia.TypefaceFontProvider.Make();
207
+ provider.registerFont(robotoRegular, "Roboto");
208
+
209
+ const builder = Skia.ParagraphBuilder.Make(
210
+ {
211
+ textStyle: {
212
+ color: Skia.Color("black"),
213
+ fontFamilies: ["Roboto"],
214
+ fontSize: 16,
215
+ },
216
+ },
217
+ provider
218
+ );
219
+
220
+ builder.addText(
221
+ "This is a very long text that should wrap to multiple lines when laid out with a narrow width constraint"
222
+ );
223
+
224
+ const paragraph = builder.build();
225
+ paragraph.layout(100); // Narrow width to force wrapping
226
+
227
+ return paragraph.getLineMetrics();
228
+ },
229
+ {
230
+ RobotoRegular,
231
+ }
232
+ );
233
+
234
+ expect(lineMetrics.length).toBeGreaterThan(1);
235
+
236
+ // Check first line
237
+ expect(lineMetrics[0].lineNumber).toBe(0);
238
+ expect(lineMetrics[0].startIndex).toBe(0);
239
+ expect(lineMetrics[0].width).toBeLessThanOrEqual(100);
240
+
241
+ // Check second line
242
+ expect(lineMetrics[1].lineNumber).toBe(1);
243
+ expect(lineMetrics[1].startIndex).toBeGreaterThan(0);
244
+ expect(lineMetrics[1].baseline).toBeGreaterThan(lineMetrics[0].baseline);
245
+ });
246
+
247
+ it("should handle hard breaks (newlines) correctly", async () => {
248
+ const lineMetrics = await surface.eval(
249
+ (Skia, ctx) => {
250
+ const robotoRegular = Skia.Typeface.MakeFreeTypeFaceFromData(
251
+ Skia.Data.fromBytes(new Uint8Array(ctx.RobotoRegular))
252
+ )!;
253
+ const provider = Skia.TypefaceFontProvider.Make();
254
+ provider.registerFont(robotoRegular, "Roboto");
255
+
256
+ const builder = Skia.ParagraphBuilder.Make(
257
+ {
258
+ textStyle: {
259
+ color: Skia.Color("black"),
260
+ fontFamilies: ["Roboto"],
261
+ fontSize: 16,
262
+ },
263
+ },
264
+ provider
265
+ );
266
+
267
+ builder.addText("First line\nSecond line\nThird line");
268
+
269
+ const paragraph = builder.build();
270
+ paragraph.layout(300);
271
+
272
+ return paragraph.getLineMetrics();
273
+ },
274
+ {
275
+ RobotoRegular,
276
+ }
277
+ );
278
+
279
+ expect(lineMetrics).toHaveLength(3);
280
+
281
+ // All lines report isHardBreak as true in this implementation
282
+ expect(lineMetrics[0].isHardBreak).toBe(true);
283
+ expect(lineMetrics[1].isHardBreak).toBe(true);
284
+ expect(lineMetrics[2].isHardBreak).toBe(true);
285
+
286
+ // Check line numbers
287
+ expect(lineMetrics[0].lineNumber).toBe(0);
288
+ expect(lineMetrics[1].lineNumber).toBe(1);
289
+ expect(lineMetrics[2].lineNumber).toBe(2);
290
+ });
291
+
292
+ it("should correctly report line dimensions and positions", async () => {
293
+ const lineMetrics = await surface.eval(
294
+ (Skia, ctx) => {
295
+ const robotoRegular = Skia.Typeface.MakeFreeTypeFaceFromData(
296
+ Skia.Data.fromBytes(new Uint8Array(ctx.RobotoRegular))
297
+ )!;
298
+ const provider = Skia.TypefaceFontProvider.Make();
299
+ provider.registerFont(robotoRegular, "Roboto");
300
+
301
+ const builder = Skia.ParagraphBuilder.Make(
302
+ {
303
+ textStyle: {
304
+ color: Skia.Color("black"),
305
+ fontFamilies: ["Roboto"],
306
+ fontSize: 20,
307
+ },
308
+ },
309
+ provider
310
+ );
311
+
312
+ builder.addText("Test\nLine");
313
+
314
+ const paragraph = builder.build();
315
+ paragraph.layout(300);
316
+
317
+ return paragraph.getLineMetrics();
318
+ },
319
+ {
320
+ RobotoRegular,
321
+ }
322
+ );
323
+
324
+ expect(lineMetrics).toHaveLength(2);
325
+
326
+ // First line
327
+ const firstLine = lineMetrics[0];
328
+ // Height should be close to ascent + descent
329
+ expect(firstLine.height).toBeGreaterThan(0);
330
+ expect(Math.abs(firstLine.height - (firstLine.ascent + firstLine.descent))).toBeLessThan(1);
331
+ expect(firstLine.left).toBe(0);
332
+ expect(firstLine.baseline).toBeGreaterThan(0);
333
+
334
+ // Second line should be below the first
335
+ const secondLine = lineMetrics[1];
336
+ expect(secondLine.baseline).toBeGreaterThan(firstLine.baseline);
337
+ expect(secondLine.baseline - firstLine.baseline).toBeCloseTo(firstLine.height, 1);
338
+ });
339
+
340
+ it("should handle empty lines correctly", async () => {
341
+ const lineMetrics = await surface.eval(
342
+ (Skia, ctx) => {
343
+ const robotoRegular = Skia.Typeface.MakeFreeTypeFaceFromData(
344
+ Skia.Data.fromBytes(new Uint8Array(ctx.RobotoRegular))
345
+ )!;
346
+ const provider = Skia.TypefaceFontProvider.Make();
347
+ provider.registerFont(robotoRegular, "Roboto");
348
+
349
+ const builder = Skia.ParagraphBuilder.Make(
350
+ {
351
+ textStyle: {
352
+ color: Skia.Color("black"),
353
+ fontFamilies: ["Roboto"],
354
+ fontSize: 16,
355
+ },
356
+ },
357
+ provider
358
+ );
359
+
360
+ builder.addText("Line 1\n\nLine 3");
361
+
362
+ const paragraph = builder.build();
363
+ paragraph.layout(300);
364
+
365
+ return paragraph.getLineMetrics();
366
+ },
367
+ {
368
+ RobotoRegular,
369
+ }
370
+ );
371
+
372
+ expect(lineMetrics).toHaveLength(3);
373
+
374
+ // Middle line should be empty but still have metrics
375
+ const emptyLine = lineMetrics[1];
376
+ // Empty line might have startIndex != endIndex depending on implementation
377
+ expect(emptyLine.endIndex).toBeGreaterThanOrEqual(emptyLine.startIndex);
378
+ expect(emptyLine.width).toBeGreaterThanOrEqual(0);
379
+ expect(emptyLine.height).toBeGreaterThan(0); // Still has height
380
+ expect(emptyLine.isHardBreak).toBe(true);
381
+ });
382
+ });
383
+ });
@@ -4,6 +4,37 @@ import type { SkRect } from "../Rect";
4
4
 
5
5
  import type { TextDirection } from "./ParagraphStyle";
6
6
 
7
+ export interface LineMetrics {
8
+ /** The index in the text buffer the line begins. */
9
+ startIndex: number;
10
+ /** The index in the text buffer the line ends. */
11
+ endIndex: number;
12
+ endExcludingWhitespaces: number;
13
+ endIncludingNewline: number;
14
+ /** True if the line ends in a hard break (e.g. newline) */
15
+ isHardBreak: boolean;
16
+ /**
17
+ * The final computed ascent for the line. This can be impacted by
18
+ * the strut, height, scaling, as well as outlying runs that are very tall.
19
+ */
20
+ ascent: number;
21
+ /**
22
+ * The final computed descent for the line. This can be impacted by
23
+ * the strut, height, scaling, as well as outlying runs that are very tall.
24
+ */
25
+ descent: number;
26
+ /** round(ascent + descent) */
27
+ height: number;
28
+ /** width of the line */
29
+ width: number;
30
+ /** The left edge of the line. The right edge can be obtained with `left + width` */
31
+ left: number;
32
+ /** The y position of the baseline for this line from the top of the paragraph. */
33
+ baseline: number;
34
+ /** Zero indexed line number. */
35
+ lineNumber: number;
36
+ }
37
+
7
38
  export interface SkRectWithDirection {
8
39
  rect: SkRect;
9
40
  direction: TextDirection;
@@ -75,7 +106,7 @@ export interface SkParagraph extends SkJSIInstance<"Paragraph"> {
75
106
  * Returns the bounding boxes for all lines in the paragraph. This method
76
107
  * requires the layout method to have been called first.
77
108
  */
78
- getLineMetrics(): Array<SkRect>;
109
+ getLineMetrics(): LineMetrics[];
79
110
  /**
80
111
  * Returns a list of rects with direction info for the placeholders added
81
112
  * to the paragraph.
@@ -1,9 +1,15 @@
1
1
  import type { CanvasKit, Paragraph } from "canvaskit-wasm";
2
2
 
3
- import type { SkRect, SkRectWithDirection, SkParagraph } from "../types";
3
+ import type {
4
+ SkRect,
5
+ SkRectWithDirection,
6
+ SkParagraph,
7
+ LineMetrics,
8
+ } from "../types";
4
9
 
5
10
  import { HostObject } from "./Host";
6
11
  import type { JsiSkCanvas } from "./JsiSkCanvas";
12
+ import { JsiSkRect } from "./JsiSkRect";
7
13
 
8
14
  export class JsiSkParagraph
9
15
  extends HostObject<Paragraph, "Paragraph">
@@ -12,41 +18,36 @@ export class JsiSkParagraph
12
18
  constructor(CanvasKit: CanvasKit, ref: Paragraph) {
13
19
  super(CanvasKit, ref, "Paragraph");
14
20
  }
15
- getMinIntrinsicWidth(): number {
21
+ getMinIntrinsicWidth() {
16
22
  return this.ref.getMinIntrinsicWidth();
17
23
  }
18
24
 
19
- getMaxIntrinsicWidth(): number {
25
+ getMaxIntrinsicWidth() {
20
26
  return this.ref.getMaxIntrinsicWidth();
21
27
  }
22
28
 
23
- getLongestLine(): number {
29
+ getLongestLine() {
24
30
  return this.ref.getLongestLine();
25
31
  }
26
32
 
27
- layout(width: number): void {
33
+ layout(width: number) {
28
34
  this.ref.layout(width);
29
35
  }
30
- paint(canvas: JsiSkCanvas, x: number, y: number): void {
36
+ paint(canvas: JsiSkCanvas, x: number, y: number) {
31
37
  canvas.ref.drawParagraph(this.ref, x, y);
32
38
  }
33
- getHeight(): number {
39
+ getHeight() {
34
40
  return this.ref.getHeight();
35
41
  }
36
- getMaxWidth(): number {
42
+ getMaxWidth() {
37
43
  return this.ref.getMaxWidth();
38
44
  }
39
- getGlyphPositionAtCoordinate(x: number, y: number): number {
45
+ getGlyphPositionAtCoordinate(x: number, y: number) {
40
46
  return this.ref.getGlyphPositionAtCoordinate(x, y).pos;
41
47
  }
42
48
  getRectsForPlaceholders(): SkRectWithDirection[] {
43
49
  return this.ref.getRectsForPlaceholders().map(({ rect, dir }) => ({
44
- rect: {
45
- x: rect.at(0)!,
46
- y: rect.at(1)!,
47
- width: rect.at(2)!,
48
- height: rect.at(3)!,
49
- },
50
+ rect: new JsiSkRect(this.CanvasKit, rect),
50
51
  direction: dir.value,
51
52
  }));
52
53
  }
@@ -58,20 +59,10 @@ export class JsiSkParagraph
58
59
  { value: 0 } /** kTight */,
59
60
  { value: 0 } /** kTight */
60
61
  )
61
- .map(({ rect }) => ({
62
- x: rect[0],
63
- y: rect[1],
64
- width: rect[2],
65
- height: rect[3],
66
- }));
62
+ .map(({ rect }) => new JsiSkRect(this.CanvasKit, rect));
67
63
  }
68
- getLineMetrics(): SkRect[] {
69
- return this.ref.getLineMetrics().map((r, index) => ({
70
- x: r.left,
71
- y: index * r.height,
72
- width: r.width,
73
- height: r.height,
74
- }));
64
+ getLineMetrics(): LineMetrics[] {
65
+ return this.ref.getLineMetrics();
75
66
  }
76
67
 
77
68
  dispose() {