Skip to content

Commit ac40c2b

Browse files
chrfalchwcandillon
andauthored
Add paragraph support (#1971)
--------- Co-authored-by: William Candillon <[email protected]>
1 parent 1af462c commit ac40c2b

File tree

91 files changed

+2531
-58
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+2531
-58
lines changed

docs/docs/text/paragraph.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
id: paragraph
3+
title: Paragraph
4+
sidebar_label: Paragraph
5+
slug: /text/paragraph
6+
---
7+
8+
React Native Skia offers an API to perform text layouts.
9+
Behind the scene, this API is the Skia Paragraph API.
10+
11+
12+
## Hello World
13+
14+
In the example below, we create a simple paragraph based on custom fonts.
15+
The emojis will be renderer using the emoji font available on the platform.
16+
Other system fonts will are available as well.
17+
18+
```tsx twoslash
19+
import { useMemo } from "react";
20+
import { Paragraph, Skia, useFonts } from "@shopify/react-native-skia";
21+
22+
const MyParagraph = () => {
23+
const customFontMgr = useFonts({
24+
Roboto: [
25+
require("path/to/Roboto-Regular.ttf"),
26+
require("path/to/Roboto-Medium.ttf")
27+
]
28+
});
29+
30+
const paragraph = useMemo(() => {
31+
// Are the font loaded already?
32+
if (!customFontMgr) {
33+
return null;
34+
}
35+
const textStyle = {
36+
color: Skia.Color("black"),
37+
fontFamilies: ["Roboto"],
38+
fontSize: 50,
39+
};
40+
return Skia.ParagraphBuilder.Make({}, customFontMgr)
41+
.pushStyle(textStyle)
42+
.addText("Say Hello to ")
43+
.pushStyle({ ...textStyle, fontStyle: { weight: 500 } })
44+
.addText("Skia 🎨")
45+
.pop()
46+
.build();
47+
}, [customFontMgr]);
48+
49+
// Render the paragraph
50+
return <Paragraph paragraph={paragraph} x={0} y={0} width={300} />;
51+
};
52+
```
53+
54+
Below is the result on Android (left) and iOS (right).
55+
<img src={require("/static/img/paragraph/hello-world-android.png").default} width="256" height="256" />
56+
<img src={require("/static/img/paragraph/hello-world-ios.png").default} width="256" height="256" />
57+
58+
On Web, you will need to provide you own emoji font ([NotoColorEmoji](https://fonts.google.com/noto/specimen/Noto+Color+Emoji) for instance) and add it to the list of font families.
59+
60+
```tsx twoslash
61+
import { useFonts, Skia } from "@shopify/react-native-skia";
62+
63+
const customFontMgr = useFonts({
64+
Roboto: [
65+
require("path/to/Roboto-Regular.ttf"),
66+
require("path/to/Roboto-Medium.ttf")
67+
],
68+
// Only load the emoji font on Web
69+
Noto: [
70+
require("path/to/NotoColorEmoji.ttf")
71+
]
72+
});
73+
74+
// We add Noto to the list of font families
75+
const textStyle = {
76+
color: Skia.Color("black"),
77+
fontFamilies: ["Roboto", "Noto"],
78+
fontSize: 50,
79+
};
80+
```
81+
82+
## Styling Paragraphs
83+
84+
These properties define the overall layout and behavior of a paragraph.
85+
86+
| Property | Description |
87+
|-------------------------|---------------------------------------------------------------------------------------|
88+
| `disableHinting` | Controls whether text hinting is disabled. |
89+
| `ellipsis` | Specifies the text to use for ellipsis when text overflows. |
90+
| `heightMultiplier` | Sets the line height as a multiplier of the font size. |
91+
| `maxLines` | Maximum number of lines for the paragraph. |
92+
| `replaceTabCharacters` | Determines whether tab characters should be replaced with spaces. |
93+
| `strutStyle` | Defines the strut style, which affects the minimum height of a line. |
94+
| `textAlign` | Sets the alignment of text (left, right, center, justify, start, end). |
95+
| `textDirection` | Determines the text direction (RTL or LTR). |
96+
| `textHeightBehavior` | Controls the behavior of text ascent and descent in the first and last lines. |
97+
| `textStyle` | Default text style for the paragraph (can be overridden by individual text styles). |
98+
99+
### Text Style Properties
100+
101+
These properties are used to style specific segments of text within a paragraph.
102+
103+
| Property | Description |
104+
|-----------------------|-------------------------------------------------------------------------------------|
105+
| `backgroundColor` | Background color of the text. |
106+
| `color` | Color of the text. |
107+
| `decoration` | Type of text decoration (underline, overline, line-through). |
108+
| `decorationColor` | Color of the text decoration. |
109+
| `decorationThickness` | Thickness of the text decoration. |
110+
| `decorationStyle` | Style of the text decoration (solid, double, dotted, dashed, wavy). |
111+
| `fontFamilies` | List of font families for the text. |
112+
| `fontFeatures` | List of font features. |
113+
| `fontSize` | Font size of the text. |
114+
| `fontStyle` | Font style (weight, width, slant). |
115+
| `fontVariations` | Font variations. |
116+
| `foregroundColor` | Foreground color (for effects like gradients). |
117+
| `heightMultiplier` | Multiplier for line height. |
118+
| `halfLeading` | Controls half-leading value. |
119+
| `letterSpacing` | Space between characters. |
120+
| `locale` | Locale for the text (affects things like sorting). |
121+
| `shadows` | List of text shadows. |
122+
| `textBaseline` | Baseline for the text (alphabetic, ideographic). |
123+
| `wordSpacing` | Space between words. |
124+
125+
These tables offer a quick reference to differentiate between paragraph and text styles in React Native Skia. You can use them to guide developers on how to apply various styles to create visually appealing and functional text layouts.
126+
Below is an example using different font styling:
127+
128+
```tsx twoslash
129+
import { useMemo } from "react";
130+
import { Paragraph, Skia, useFonts, FontStyle } from "@shopify/react-native-skia";
131+
132+
const MyParagraph = () => {
133+
const customFontMgr = useFonts({
134+
Roboto: [
135+
require("path/to/Roboto-Italic.ttf"),
136+
require("path/to/Roboto-Regular.ttf"),
137+
require("path/to/Roboto-Bold.ttf")
138+
],
139+
});
140+
141+
const paragraph = useMemo(() => {
142+
// Are the custom fonts loaded?
143+
if (!customFontMgr) {
144+
return null;
145+
}
146+
const textStyle = {
147+
fontSize: 24,
148+
fontFamilies: ["Roboto"],
149+
color: Skia.Color("#000"),
150+
};
151+
152+
const paragraphBuilder = Skia.ParagraphBuilder.Make({}, customFontMgr);
153+
paragraphBuilder
154+
.pushStyle({ ...textStyle, fontStyle: FontStyle.Bold })
155+
.addText("This text is bold\n")
156+
.pop()
157+
.pushStyle({ ...textStyle, fontStyle: FontStyle.Normal })
158+
.addText("This text is regular\n")
159+
.pop()
160+
.pushStyle({ ...textStyle, fontStyle: FontStyle.Italic })
161+
.addText("This text is italic")
162+
.pop()
163+
.build();
164+
return paragraphBuilder.build();
165+
}, [customFontMgr]);
166+
167+
return <Paragraph paragraph={paragraph} x={0} y={0} width={300} />;
168+
};
169+
```
170+
171+
#### Result
172+
173+
<img src={require("/static/img/paragraph/font-style-node.png").default} width="256" height="256" />

docs/sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const sidebars = {
6969
label: "Text",
7070
items: [
7171
"text/fonts",
72+
"text/paragraph",
7273
"text/text",
7374
"text/glyphs",
7475
"text/path",
22 KB
Loading
22.4 KB
Loading
22.2 KB
Loading
38.2 KB
Loading
52.6 KB
Loading
38.3 KB
Loading

example/ios/Podfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,12 @@ target 'RNSkia' do
5757
:mac_catalyst_enabled => false
5858
)
5959
__apply_Xcode_12_5_M1_post_install_workaround(installer)
60+
61+
# Fix issue with No template named 'unary_function' in namespace in XCode 15
62+
installer.pods_project.targets.each do |target|
63+
target.build_configurations.each do |config|
64+
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION']
65+
end
66+
end
6067
end
6168
end

example/ios/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,6 @@ SPEC CHECKSUMS:
689689
Yoga: d56980c8914db0b51692f55533409e844b66133c
690690
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
691691

692-
PODFILE CHECKSUM: 131fa288ba44bcbe1eff8b491f2c5a7f95d8f3a8
692+
PODFILE CHECKSUM: 3bf5d3cf7d3fe342535cb3ff9d97c0af632863ce
693693

694694
COCOAPODS: 1.11.3

0 commit comments

Comments
 (0)