1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.compose.ui.text
18 
19 import androidx.compose.runtime.Immutable
20 import androidx.compose.runtime.Stable
21 import androidx.compose.ui.graphics.Brush
22 import androidx.compose.ui.graphics.Color
23 import androidx.compose.ui.graphics.Shadow
24 import androidx.compose.ui.graphics.drawscope.DrawStyle
25 import androidx.compose.ui.text.font.FontFamily
26 import androidx.compose.ui.text.font.FontStyle
27 import androidx.compose.ui.text.font.FontSynthesis
28 import androidx.compose.ui.text.font.FontWeight
29 import androidx.compose.ui.text.intl.LocaleList
30 import androidx.compose.ui.text.style.BaselineShift
31 import androidx.compose.ui.text.style.Hyphens
32 import androidx.compose.ui.text.style.LineBreak
33 import androidx.compose.ui.text.style.LineHeightStyle
34 import androidx.compose.ui.text.style.TextAlign
35 import androidx.compose.ui.text.style.TextDecoration
36 import androidx.compose.ui.text.style.TextDirection
37 import androidx.compose.ui.text.style.TextForegroundStyle
38 import androidx.compose.ui.text.style.TextGeometricTransform
39 import androidx.compose.ui.text.style.TextIndent
40 import androidx.compose.ui.text.style.TextMotion
41 import androidx.compose.ui.unit.LayoutDirection
42 import androidx.compose.ui.unit.TextUnit
43 import kotlin.jvm.JvmName
44 
45 /**
46  * Styling configuration for a `Text`.
47  *
48  * @sample androidx.compose.ui.text.samples.TextStyleSample
49  * @param platformStyle Platform specific [TextStyle] parameters.
50  * @see AnnotatedString
51  * @see SpanStyle
52  * @see ParagraphStyle
53  */
54 // Maintainer note: When adding a new constructor or copy parameter, make sure to add a test case to
55 // TextStyleInvalidationTest to ensure the correct phase(s) get invalidated.
56 @Immutable
57 class TextStyle
58 internal constructor(
59     internal val spanStyle: SpanStyle,
60     internal val paragraphStyle: ParagraphStyle,
61     val platformStyle: PlatformTextStyle? = null,
62 ) {
63     internal constructor(
64         spanStyle: SpanStyle,
65         paragraphStyle: ParagraphStyle,
66     ) : this(
67         spanStyle = spanStyle,
68         paragraphStyle = paragraphStyle,
69         platformStyle =
70             createPlatformTextStyleInternal(spanStyle.platformStyle, paragraphStyle.platformStyle)
71     )
72 
73     @Deprecated(
74         "TextStyle constructors that do not take new stable parameters " +
75             "like LineHeightStyle, LineBreak, Hyphens are deprecated. Please use the new stable " +
76             "constructor.",
77         level = DeprecationLevel.HIDDEN
78     )
79     constructor(
80         color: Color = Color.Unspecified,
81         fontSize: TextUnit = TextUnit.Unspecified,
82         fontWeight: FontWeight? = null,
83         fontStyle: FontStyle? = null,
84         fontSynthesis: FontSynthesis? = null,
85         fontFamily: FontFamily? = null,
86         fontFeatureSettings: String? = null,
87         letterSpacing: TextUnit = TextUnit.Unspecified,
88         baselineShift: BaselineShift? = null,
89         textGeometricTransform: TextGeometricTransform? = null,
90         localeList: LocaleList? = null,
91         background: Color = Color.Unspecified,
92         textDecoration: TextDecoration? = null,
93         shadow: Shadow? = null,
94         textAlign: TextAlign? = null,
95         textDirection: TextDirection? = null,
96         lineHeight: TextUnit = TextUnit.Unspecified,
97         textIndent: TextIndent? = null
98     ) : this(
99         SpanStyle(
100             color = color,
101             fontSize = fontSize,
102             fontWeight = fontWeight,
103             fontStyle = fontStyle,
104             fontSynthesis = fontSynthesis,
105             fontFamily = fontFamily,
106             fontFeatureSettings = fontFeatureSettings,
107             letterSpacing = letterSpacing,
108             baselineShift = baselineShift,
109             textGeometricTransform = textGeometricTransform,
110             localeList = localeList,
111             background = background,
112             textDecoration = textDecoration,
113             shadow = shadow,
114             platformStyle = null,
115             drawStyle = null
116         ),
117         ParagraphStyle(
118             textAlign = textAlign ?: TextAlign.Unspecified,
119             textDirection = textDirection ?: TextDirection.Unspecified,
120             lineHeight = lineHeight,
121             textIndent = textIndent,
122             platformStyle = null,
123             lineHeightStyle = null,
124             lineBreak = LineBreak.Unspecified,
125             hyphens = Hyphens.Unspecified,
126             textMotion = null
127         ),
128         platformStyle = null
129     )
130 
131     @Deprecated(
132         "TextStyle constructors that do not take new stable parameters " +
133             "like LineHeightStyle, LineBreak, Hyphens are deprecated. Please use the new stable " +
134             "constructor.",
135         level = DeprecationLevel.HIDDEN
136     )
137     constructor(
138         color: Color = Color.Unspecified,
139         fontSize: TextUnit = TextUnit.Unspecified,
140         fontWeight: FontWeight? = null,
141         fontStyle: FontStyle? = null,
142         fontSynthesis: FontSynthesis? = null,
143         fontFamily: FontFamily? = null,
144         fontFeatureSettings: String? = null,
145         letterSpacing: TextUnit = TextUnit.Unspecified,
146         baselineShift: BaselineShift? = null,
147         textGeometricTransform: TextGeometricTransform? = null,
148         localeList: LocaleList? = null,
149         background: Color = Color.Unspecified,
150         textDecoration: TextDecoration? = null,
151         shadow: Shadow? = null,
152         textAlign: TextAlign? = null,
153         textDirection: TextDirection? = null,
154         lineHeight: TextUnit = TextUnit.Unspecified,
155         textIndent: TextIndent? = null,
156         platformStyle: PlatformTextStyle? = null,
157         lineHeightStyle: LineHeightStyle? = null
158     ) : this(
159         SpanStyle(
160             color = color,
161             fontSize = fontSize,
162             fontWeight = fontWeight,
163             fontStyle = fontStyle,
164             fontSynthesis = fontSynthesis,
165             fontFamily = fontFamily,
166             fontFeatureSettings = fontFeatureSettings,
167             letterSpacing = letterSpacing,
168             baselineShift = baselineShift,
169             textGeometricTransform = textGeometricTransform,
170             localeList = localeList,
171             background = background,
172             textDecoration = textDecoration,
173             shadow = shadow,
174             platformStyle = platformStyle?.spanStyle,
175             drawStyle = null
176         ),
177         ParagraphStyle(
178             textAlign = textAlign ?: TextAlign.Unspecified,
179             textDirection = textDirection ?: TextDirection.Unspecified,
180             lineHeight = lineHeight,
181             textIndent = textIndent,
182             platformStyle = platformStyle?.paragraphStyle,
183             lineHeightStyle = lineHeightStyle,
184             lineBreak = LineBreak.Unspecified,
185             hyphens = Hyphens.Unspecified,
186             textMotion = null
187         ),
188         platformStyle = platformStyle
189     )
190 
191     /**
192      * Styling configuration for a `Text`.
193      *
194      * @sample androidx.compose.ui.text.samples.TextStyleSample
195      * @param color The text color.
196      * @param fontSize The size of glyphs to use when painting the text. This may be
197      *   [TextUnit.Unspecified] for inheriting from another [TextStyle].
198      * @param fontWeight The typeface thickness to use when painting the text (e.g., bold).
199      * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
200      * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight
201      *   or style cannot be found in the provided font family.
202      * @param fontFamily The font family to be used when rendering the text.
203      * @param fontFeatureSettings The advanced typography settings provided by font. The format is
204      *   the same as the CSS font-feature-settings attribute:
205      *   https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop
206      * @param letterSpacing The amount of space to add between each letter.
207      * @param baselineShift The amount by which the text is shifted up from the current baseline.
208      * @param textGeometricTransform The geometric transformation applied the text.
209      * @param localeList The locale list used to select region-specific glyphs.
210      * @param background The background color for the text.
211      * @param textDecoration The decorations to paint on the text (e.g., an underline).
212      * @param shadow The shadow effect applied on the text.
213      * @param textAlign The alignment of the text within the lines of the paragraph.
214      * @param textDirection The algorithm to be used to resolve the final text and paragraph
215      *   direction: Left To Right or Right To Left. If no value is provided the system will use the
216      *   [LayoutDirection] as the primary signal.
217      * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
218      * @param textIndent The indentation of the paragraph.
219      * @param platformStyle Platform specific [TextStyle] parameters.
220      * @param lineHeightStyle the configuration for line height such as vertical alignment of the
221      *   line, whether to apply additional space as a result of line height to top of first line top
222      *   and bottom of last line. The configuration is applied only when a [lineHeight] is defined.
223      *   When null, [LineHeightStyle.Default] is used.
224      * @param lineBreak The line breaking configuration for the text.
225      * @param hyphens The configuration of hyphenation.
226      */
227     @Deprecated(
228         "TextStyle constructors that do not take new stable parameters " +
229             "like TextMotion are deprecated. Please use the new stable " +
230             "constructor.",
231         level = DeprecationLevel.HIDDEN
232     )
233     constructor(
234         color: Color = Color.Unspecified,
235         fontSize: TextUnit = TextUnit.Unspecified,
236         fontWeight: FontWeight? = null,
237         fontStyle: FontStyle? = null,
238         fontSynthesis: FontSynthesis? = null,
239         fontFamily: FontFamily? = null,
240         fontFeatureSettings: String? = null,
241         letterSpacing: TextUnit = TextUnit.Unspecified,
242         baselineShift: BaselineShift? = null,
243         textGeometricTransform: TextGeometricTransform? = null,
244         localeList: LocaleList? = null,
245         background: Color = Color.Unspecified,
246         textDecoration: TextDecoration? = null,
247         shadow: Shadow? = null,
248         textAlign: TextAlign? = null,
249         textDirection: TextDirection? = null,
250         lineHeight: TextUnit = TextUnit.Unspecified,
251         textIndent: TextIndent? = null,
252         platformStyle: PlatformTextStyle? = null,
253         lineHeightStyle: LineHeightStyle? = null,
254         lineBreak: LineBreak? = null,
255         hyphens: Hyphens? = null
256     ) : this(
257         SpanStyle(
258             color = color,
259             fontSize = fontSize,
260             fontWeight = fontWeight,
261             fontStyle = fontStyle,
262             fontSynthesis = fontSynthesis,
263             fontFamily = fontFamily,
264             fontFeatureSettings = fontFeatureSettings,
265             letterSpacing = letterSpacing,
266             baselineShift = baselineShift,
267             textGeometricTransform = textGeometricTransform,
268             localeList = localeList,
269             background = background,
270             textDecoration = textDecoration,
271             shadow = shadow,
272             platformStyle = platformStyle?.spanStyle
273         ),
274         ParagraphStyle(
275             textAlign = textAlign ?: TextAlign.Unspecified,
276             textDirection = textDirection ?: TextDirection.Unspecified,
277             lineHeight = lineHeight,
278             textIndent = textIndent,
279             platformStyle = platformStyle?.paragraphStyle,
280             lineHeightStyle = lineHeightStyle,
281             lineBreak = lineBreak ?: LineBreak.Unspecified,
282             hyphens = hyphens ?: Hyphens.Unspecified
283         ),
284         platformStyle = platformStyle
285     )
286 
287     @Deprecated(
288         "TextStyle constructors that take nullable TextAlign, " +
289             "TextDirection, LineBreak, and Hyphens are deprecated. Please use a new constructor " +
290             "where these parameters are non-nullable. Null value has been replaced by a special " +
291             "Unspecified object for performance reason.",
292         level = DeprecationLevel.HIDDEN
293     )
294     constructor(
295         color: Color = Color.Unspecified,
296         fontSize: TextUnit = TextUnit.Unspecified,
297         fontWeight: FontWeight? = null,
298         fontStyle: FontStyle? = null,
299         fontSynthesis: FontSynthesis? = null,
300         fontFamily: FontFamily? = null,
301         fontFeatureSettings: String? = null,
302         letterSpacing: TextUnit = TextUnit.Unspecified,
303         baselineShift: BaselineShift? = null,
304         textGeometricTransform: TextGeometricTransform? = null,
305         localeList: LocaleList? = null,
306         background: Color = Color.Unspecified,
307         textDecoration: TextDecoration? = null,
308         shadow: Shadow? = null,
309         drawStyle: DrawStyle? = null,
310         textAlign: TextAlign? = null,
311         textDirection: TextDirection? = null,
312         lineHeight: TextUnit = TextUnit.Unspecified,
313         textIndent: TextIndent? = null,
314         platformStyle: PlatformTextStyle? = null,
315         lineHeightStyle: LineHeightStyle? = null,
316         lineBreak: LineBreak? = null,
317         hyphens: Hyphens? = null,
318         textMotion: TextMotion? = null,
319     ) : this(
320         SpanStyle(
321             color = color,
322             fontSize = fontSize,
323             fontWeight = fontWeight,
324             fontStyle = fontStyle,
325             fontSynthesis = fontSynthesis,
326             fontFamily = fontFamily,
327             fontFeatureSettings = fontFeatureSettings,
328             letterSpacing = letterSpacing,
329             baselineShift = baselineShift,
330             textGeometricTransform = textGeometricTransform,
331             localeList = localeList,
332             background = background,
333             textDecoration = textDecoration,
334             shadow = shadow,
335             platformStyle = platformStyle?.spanStyle,
336             drawStyle = drawStyle
337         ),
338         ParagraphStyle(
339             textAlign = textAlign ?: TextAlign.Unspecified,
340             textDirection = textDirection ?: TextDirection.Unspecified,
341             lineHeight = lineHeight,
342             textIndent = textIndent,
343             platformStyle = platformStyle?.paragraphStyle,
344             lineHeightStyle = lineHeightStyle,
345             lineBreak = lineBreak ?: LineBreak.Unspecified,
346             hyphens = hyphens ?: Hyphens.Unspecified,
347             textMotion = textMotion
348         ),
349         platformStyle = platformStyle
350     )
351 
352     /**
353      * Styling configuration for a `Text`.
354      *
355      * @sample androidx.compose.ui.text.samples.TextStyleSample
356      * @param color The text color.
357      * @param fontSize The size of glyphs to use when painting the text. This may be
358      *   [TextUnit.Unspecified] for inheriting from another [TextStyle].
359      * @param fontWeight The typeface thickness to use when painting the text (e.g., bold).
360      * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
361      * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight
362      *   or style cannot be found in the provided font family.
363      * @param fontFamily The font family to be used when rendering the text.
364      * @param fontFeatureSettings The advanced typography settings provided by font. The format is
365      *   the same as the CSS font-feature-settings attribute:
366      *   https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop
367      * @param letterSpacing The amount of space to add between each letter.
368      * @param baselineShift The amount by which the text is shifted up from the current baseline.
369      * @param textGeometricTransform The geometric transformation applied the text.
370      * @param localeList The locale list used to select region-specific glyphs.
371      * @param background The background color for the text.
372      * @param textDecoration The decorations to paint on the text (e.g., an underline).
373      * @param shadow The shadow effect applied on the text.
374      * @param drawStyle Drawing style of text, whether fill in the text while drawing or stroke
375      *   around the edges.
376      * @param textAlign The alignment of the text within the lines of the paragraph.
377      * @param textDirection The algorithm to be used to resolve the final text and paragraph
378      *   direction: Left To Right or Right To Left. If no value is provided the system will use the
379      *   [LayoutDirection] as the primary signal.
380      * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
381      * @param textIndent The indentation of the paragraph.
382      * @param platformStyle Platform specific [TextStyle] parameters.
383      * @param lineHeightStyle the configuration for line height such as vertical alignment of the
384      *   line, whether to apply additional space as a result of line height to top of first line top
385      *   and bottom of last line. The configuration is applied only when a [lineHeight] is defined.
386      *   When null, [LineHeightStyle.Default] is used.
387      * @param lineBreak The line breaking configuration for the text.
388      * @param hyphens The configuration of hyphenation.
389      * @param textMotion Text character placement, whether to optimize for animated or static text.
390      */
391     constructor(
392         color: Color = Color.Unspecified,
393         fontSize: TextUnit = TextUnit.Unspecified,
394         fontWeight: FontWeight? = null,
395         fontStyle: FontStyle? = null,
396         fontSynthesis: FontSynthesis? = null,
397         fontFamily: FontFamily? = null,
398         fontFeatureSettings: String? = null,
399         letterSpacing: TextUnit = TextUnit.Unspecified,
400         baselineShift: BaselineShift? = null,
401         textGeometricTransform: TextGeometricTransform? = null,
402         localeList: LocaleList? = null,
403         background: Color = Color.Unspecified,
404         textDecoration: TextDecoration? = null,
405         shadow: Shadow? = null,
406         drawStyle: DrawStyle? = null,
407         textAlign: TextAlign = TextAlign.Unspecified,
408         textDirection: TextDirection = TextDirection.Unspecified,
409         lineHeight: TextUnit = TextUnit.Unspecified,
410         textIndent: TextIndent? = null,
411         platformStyle: PlatformTextStyle? = null,
412         lineHeightStyle: LineHeightStyle? = null,
413         lineBreak: LineBreak = LineBreak.Unspecified,
414         hyphens: Hyphens = Hyphens.Unspecified,
415         textMotion: TextMotion? = null,
416     ) : this(
417         SpanStyle(
418             color = color,
419             fontSize = fontSize,
420             fontWeight = fontWeight,
421             fontStyle = fontStyle,
422             fontSynthesis = fontSynthesis,
423             fontFamily = fontFamily,
424             fontFeatureSettings = fontFeatureSettings,
425             letterSpacing = letterSpacing,
426             baselineShift = baselineShift,
427             textGeometricTransform = textGeometricTransform,
428             localeList = localeList,
429             background = background,
430             textDecoration = textDecoration,
431             shadow = shadow,
432             platformStyle = platformStyle?.spanStyle,
433             drawStyle = drawStyle
434         ),
435         ParagraphStyle(
436             textAlign = textAlign,
437             textDirection = textDirection,
438             lineHeight = lineHeight,
439             textIndent = textIndent,
440             platformStyle = platformStyle?.paragraphStyle,
441             lineHeightStyle = lineHeightStyle,
442             lineBreak = lineBreak,
443             hyphens = hyphens,
444             textMotion = textMotion
445         ),
446         platformStyle = platformStyle
447     )
448 
449     /**
450      * Styling configuration for a `Text`.
451      *
452      * @sample androidx.compose.ui.text.samples.TextStyleBrushSample
453      * @param brush The brush to use when painting the text. If brush is given as null, it will be
454      *   treated as unspecified. It is equivalent to calling the alternative color constructor with
455      *   [Color.Unspecified]
456      * @param alpha Opacity to be applied to [brush] from 0.0f to 1.0f representing fully
457      *   transparent to fully opaque respectively.
458      * @param fontSize The size of glyphs to use when painting the text. This may be
459      *   [TextUnit.Unspecified] for inheriting from another [TextStyle].
460      * @param fontWeight The typeface thickness to use when painting the text (e.g., bold).
461      * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
462      * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight
463      *   or style cannot be found in the provided font family.
464      * @param fontFamily The font family to be used when rendering the text.
465      * @param fontFeatureSettings The advanced typography settings provided by font. The format is
466      *   the same as the CSS font-feature-settings attribute:
467      *   https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop
468      * @param letterSpacing The amount of space to add between each letter.
469      * @param baselineShift The amount by which the text is shifted up from the current baseline.
470      * @param textGeometricTransform The geometric transformation applied the text.
471      * @param localeList The locale list used to select region-specific glyphs.
472      * @param background The background color for the text.
473      * @param textDecoration The decorations to paint on the text (e.g., an underline).
474      * @param shadow The shadow effect applied on the text.
475      * @param drawStyle Drawing style of text, whether fill in the text while drawing or stroke
476      *   around the edges.
477      * @param textAlign The alignment of the text within the lines of the paragraph.
478      * @param textDirection The algorithm to be used to resolve the final text and paragraph
479      *   direction: Left To Right or Right To Left. If no value is provided the system will use the
480      *   [LayoutDirection] as the primary signal.
481      * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
482      * @param textIndent The indentation of the paragraph.
483      * @param platformStyle Platform specific [TextStyle] parameters.
484      * @param lineHeightStyle the configuration for line height such as vertical alignment of the
485      *   line, whether to apply additional space as a result of line height to top of first line top
486      *   and bottom of last line. The configuration is applied only when a [lineHeight] is defined.
487      * @param lineBreak The line breaking configuration for the text.
488      * @param hyphens The configuration of hyphenation.
489      * @param textMotion Text character placement, whether to optimize for animated or static text.
490      */
491     constructor(
492         brush: Brush?,
493         alpha: Float = Float.NaN,
494         fontSize: TextUnit = TextUnit.Unspecified,
495         fontWeight: FontWeight? = null,
496         fontStyle: FontStyle? = null,
497         fontSynthesis: FontSynthesis? = null,
498         fontFamily: FontFamily? = null,
499         fontFeatureSettings: String? = null,
500         letterSpacing: TextUnit = TextUnit.Unspecified,
501         baselineShift: BaselineShift? = null,
502         textGeometricTransform: TextGeometricTransform? = null,
503         localeList: LocaleList? = null,
504         background: Color = Color.Unspecified,
505         textDecoration: TextDecoration? = null,
506         shadow: Shadow? = null,
507         drawStyle: DrawStyle? = null,
508         textAlign: TextAlign = TextAlign.Unspecified,
509         textDirection: TextDirection = TextDirection.Unspecified,
510         lineHeight: TextUnit = TextUnit.Unspecified,
511         textIndent: TextIndent? = null,
512         platformStyle: PlatformTextStyle? = null,
513         lineHeightStyle: LineHeightStyle? = null,
514         lineBreak: LineBreak = LineBreak.Unspecified,
515         hyphens: Hyphens = Hyphens.Unspecified,
516         textMotion: TextMotion? = null
517     ) : this(
518         SpanStyle(
519             brush = brush,
520             alpha = alpha,
521             fontSize = fontSize,
522             fontWeight = fontWeight,
523             fontStyle = fontStyle,
524             fontSynthesis = fontSynthesis,
525             fontFamily = fontFamily,
526             fontFeatureSettings = fontFeatureSettings,
527             letterSpacing = letterSpacing,
528             baselineShift = baselineShift,
529             textGeometricTransform = textGeometricTransform,
530             localeList = localeList,
531             background = background,
532             textDecoration = textDecoration,
533             shadow = shadow,
534             platformStyle = platformStyle?.spanStyle,
535             drawStyle = drawStyle
536         ),
537         ParagraphStyle(
538             textAlign = textAlign,
539             textDirection = textDirection,
540             lineHeight = lineHeight,
541             textIndent = textIndent,
542             platformStyle = platformStyle?.paragraphStyle,
543             lineHeightStyle = lineHeightStyle,
544             lineBreak = lineBreak,
545             hyphens = hyphens,
546             textMotion = textMotion
547         ),
548         platformStyle = platformStyle
549     )
550 
551     @Deprecated(
552         "TextStyle constructors that take nullable TextAlign, " +
553             "TextDirection, LineBreak, and Hyphens are deprecated. Please use a new constructor " +
554             "where these parameters are non-nullable. Null value has been replaced by a special " +
555             "Unspecified object for performance reason.",
556         level = DeprecationLevel.HIDDEN
557     )
558     constructor(
559         brush: Brush?,
560         alpha: Float = Float.NaN,
561         fontSize: TextUnit = TextUnit.Unspecified,
562         fontWeight: FontWeight? = null,
563         fontStyle: FontStyle? = null,
564         fontSynthesis: FontSynthesis? = null,
565         fontFamily: FontFamily? = null,
566         fontFeatureSettings: String? = null,
567         letterSpacing: TextUnit = TextUnit.Unspecified,
568         baselineShift: BaselineShift? = null,
569         textGeometricTransform: TextGeometricTransform? = null,
570         localeList: LocaleList? = null,
571         background: Color = Color.Unspecified,
572         textDecoration: TextDecoration? = null,
573         shadow: Shadow? = null,
574         drawStyle: DrawStyle? = null,
575         textAlign: TextAlign? = null,
576         textDirection: TextDirection? = null,
577         lineHeight: TextUnit = TextUnit.Unspecified,
578         textIndent: TextIndent? = null,
579         platformStyle: PlatformTextStyle? = null,
580         lineHeightStyle: LineHeightStyle? = null,
581         lineBreak: LineBreak? = null,
582         hyphens: Hyphens? = null,
583         textMotion: TextMotion? = null
584     ) : this(
585         SpanStyle(
586             brush = brush,
587             alpha = alpha,
588             fontSize = fontSize,
589             fontWeight = fontWeight,
590             fontStyle = fontStyle,
591             fontSynthesis = fontSynthesis,
592             fontFamily = fontFamily,
593             fontFeatureSettings = fontFeatureSettings,
594             letterSpacing = letterSpacing,
595             baselineShift = baselineShift,
596             textGeometricTransform = textGeometricTransform,
597             localeList = localeList,
598             background = background,
599             textDecoration = textDecoration,
600             shadow = shadow,
601             platformStyle = platformStyle?.spanStyle,
602             drawStyle = drawStyle
603         ),
604         ParagraphStyle(
605             textAlign = textAlign ?: TextAlign.Unspecified,
606             textDirection = textDirection ?: TextDirection.Unspecified,
607             lineHeight = lineHeight,
608             textIndent = textIndent,
609             platformStyle = platformStyle?.paragraphStyle,
610             lineHeightStyle = lineHeightStyle,
611             lineBreak = lineBreak ?: LineBreak.Unspecified,
612             hyphens = hyphens ?: Hyphens.Unspecified,
613             textMotion = textMotion
614         ),
615         platformStyle = platformStyle
616     )
617 
toSpanStylenull618     @Stable fun toSpanStyle(): SpanStyle = spanStyle
619 
620     @Stable fun toParagraphStyle(): ParagraphStyle = paragraphStyle
621 
622     /**
623      * Returns a new text style that is a combination of this style and the given [other] style.
624      *
625      * [other] text style's null or inherit properties are replaced with the non-null properties of
626      * this text style. Another way to think of it is that the "missing" properties of the [other]
627      * style are _filled_ by the properties of this style.
628      *
629      * If the given text style is null, returns this text style.
630      */
631     @Stable
632     fun merge(other: TextStyle? = null): TextStyle {
633         if (other == null || other == Default) return this
634         return TextStyle(
635             spanStyle = toSpanStyle().merge(other.toSpanStyle()),
636             paragraphStyle = toParagraphStyle().merge(other.toParagraphStyle())
637         )
638     }
639 
640     /**
641      * Fast merge non-default values and parameters.
642      *
643      * This is the same algorithm as [merge] but does not require allocating it's parameter and may
644      * return this instead of allocating a result when all values are default.
645      *
646      * This is a similar algorithm to [copy] but when either this or a parameter are set to a
647      * default value, the other value will take precedent.
648      *
649      * To explain better, consider the following examples:
650      *
651      * Example 1:
652      * - this.color = [Color.Unspecified]
653      * - [color] = [Color.Red]
654      * - result => [Color.Red]
655      *
656      * Example 2:
657      * - this.color = [Color.Red]
658      * - [color] = [Color.Unspecified]
659      * - result => [Color.Red]
660      *
661      * Example 3:
662      * - this.color = [Color.Red]
663      * - [color] = [Color.Blue]
664      * - result => [Color.Blue]
665      *
666      * You should _always_ use this method over the [merge]([TextStyle]) overload when you do not
667      * already have a TextStyle allocated. You should chose this over [copy] when building a theming
668      * system and applying styling information to a specific usage.
669      *
670      * @return this or a new TextLayoutResult with all parameters chosen to the non-default option
671      *   provided.
672      * @see merge
673      */
674     @Stable
mergenull675     fun merge(
676         color: Color = Color.Unspecified,
677         fontSize: TextUnit = TextUnit.Unspecified,
678         fontWeight: FontWeight? = null,
679         fontStyle: FontStyle? = null,
680         fontSynthesis: FontSynthesis? = null,
681         fontFamily: FontFamily? = null,
682         fontFeatureSettings: String? = null,
683         letterSpacing: TextUnit = TextUnit.Unspecified,
684         baselineShift: BaselineShift? = null,
685         textGeometricTransform: TextGeometricTransform? = null,
686         localeList: LocaleList? = null,
687         background: Color = Color.Unspecified,
688         textDecoration: TextDecoration? = null,
689         shadow: Shadow? = null,
690         drawStyle: DrawStyle? = null,
691         textAlign: TextAlign = TextAlign.Unspecified,
692         textDirection: TextDirection = TextDirection.Unspecified,
693         lineHeight: TextUnit = TextUnit.Unspecified,
694         textIndent: TextIndent? = null,
695         lineHeightStyle: LineHeightStyle? = null,
696         lineBreak: LineBreak = LineBreak.Unspecified,
697         hyphens: Hyphens = Hyphens.Unspecified,
698         platformStyle: PlatformTextStyle? = null,
699         textMotion: TextMotion? = null
700     ): TextStyle {
701         val mergedSpanStyle: SpanStyle =
702             spanStyle.fastMerge(
703                 color = color,
704                 brush = null,
705                 alpha = Float.NaN,
706                 fontSize = fontSize,
707                 fontWeight = fontWeight,
708                 fontStyle = fontStyle,
709                 fontSynthesis = fontSynthesis,
710                 fontFamily = fontFamily,
711                 fontFeatureSettings = fontFeatureSettings,
712                 letterSpacing = letterSpacing,
713                 baselineShift = baselineShift,
714                 textGeometricTransform = textGeometricTransform,
715                 localeList = localeList,
716                 background = background,
717                 textDecoration = textDecoration,
718                 shadow = shadow,
719                 platformStyle = platformStyle?.spanStyle,
720                 drawStyle = drawStyle
721             )
722         val mergedParagraphStyle: ParagraphStyle =
723             paragraphStyle.fastMerge(
724                 textAlign = textAlign,
725                 textDirection = textDirection,
726                 lineHeight = lineHeight,
727                 textIndent = textIndent,
728                 platformStyle = platformStyle?.paragraphStyle,
729                 lineHeightStyle = lineHeightStyle,
730                 lineBreak = lineBreak,
731                 hyphens = hyphens,
732                 textMotion = textMotion
733             )
734         if (spanStyle === mergedSpanStyle && paragraphStyle === mergedParagraphStyle) return this
735         return TextStyle(mergedSpanStyle, mergedParagraphStyle)
736     }
737 
738     @Deprecated(
739         "merge that takes nullable TextAlign, " +
740             "TextDirection, LineBreak, and Hyphens are deprecated. Please use a new constructor " +
741             "where these parameters are non-nullable. Null value has been replaced by a special " +
742             "Unspecified object for performance reason.",
743         level = DeprecationLevel.HIDDEN
744     )
745     @Stable
mergenull746     fun merge(
747         color: Color = Color.Unspecified,
748         fontSize: TextUnit = TextUnit.Unspecified,
749         fontWeight: FontWeight? = null,
750         fontStyle: FontStyle? = null,
751         fontSynthesis: FontSynthesis? = null,
752         fontFamily: FontFamily? = null,
753         fontFeatureSettings: String? = null,
754         letterSpacing: TextUnit = TextUnit.Unspecified,
755         baselineShift: BaselineShift? = null,
756         textGeometricTransform: TextGeometricTransform? = null,
757         localeList: LocaleList? = null,
758         background: Color = Color.Unspecified,
759         textDecoration: TextDecoration? = null,
760         shadow: Shadow? = null,
761         drawStyle: DrawStyle? = null,
762         textAlign: TextAlign? = null,
763         textDirection: TextDirection? = null,
764         lineHeight: TextUnit = TextUnit.Unspecified,
765         textIndent: TextIndent? = null,
766         lineHeightStyle: LineHeightStyle? = null,
767         lineBreak: LineBreak? = null,
768         hyphens: Hyphens? = null,
769         platformStyle: PlatformTextStyle? = null,
770         textMotion: TextMotion? = null
771     ): TextStyle {
772         val mergedSpanStyle: SpanStyle =
773             spanStyle.fastMerge(
774                 color = color,
775                 brush = null,
776                 alpha = Float.NaN,
777                 fontSize = fontSize,
778                 fontWeight = fontWeight,
779                 fontStyle = fontStyle,
780                 fontSynthesis = fontSynthesis,
781                 fontFamily = fontFamily,
782                 fontFeatureSettings = fontFeatureSettings,
783                 letterSpacing = letterSpacing,
784                 baselineShift = baselineShift,
785                 textGeometricTransform = textGeometricTransform,
786                 localeList = localeList,
787                 background = background,
788                 textDecoration = textDecoration,
789                 shadow = shadow,
790                 platformStyle = platformStyle?.spanStyle,
791                 drawStyle = drawStyle
792             )
793         val mergedParagraphStyle: ParagraphStyle =
794             paragraphStyle.fastMerge(
795                 textAlign = textAlign ?: TextAlign.Unspecified,
796                 textDirection = textDirection ?: TextDirection.Unspecified,
797                 lineHeight = lineHeight,
798                 textIndent = textIndent,
799                 platformStyle = platformStyle?.paragraphStyle,
800                 lineHeightStyle = lineHeightStyle,
801                 lineBreak = lineBreak ?: LineBreak.Unspecified,
802                 hyphens = hyphens ?: Hyphens.Unspecified,
803                 textMotion = textMotion
804             )
805         if (spanStyle === mergedSpanStyle && paragraphStyle === mergedParagraphStyle) return this
806         return TextStyle(mergedSpanStyle, mergedParagraphStyle)
807     }
808 
809     /**
810      * Returns a new text style that is a combination of this style and the given [other] style.
811      *
812      * @see merge
813      */
814     @Stable
mergenull815     fun merge(other: SpanStyle): TextStyle {
816         return TextStyle(
817             spanStyle = toSpanStyle().merge(other),
818             paragraphStyle = toParagraphStyle()
819         )
820     }
821 
822     /**
823      * Returns a new text style that is a combination of this style and the given [other] style.
824      *
825      * @see merge
826      */
827     @Stable
mergenull828     fun merge(other: ParagraphStyle): TextStyle {
829         return TextStyle(
830             spanStyle = toSpanStyle(),
831             paragraphStyle = toParagraphStyle().merge(other)
832         )
833     }
834 
835     /** Plus operator overload that applies a [merge]. */
plusnull836     @Stable operator fun plus(other: TextStyle): TextStyle = this.merge(other)
837 
838     /** Plus operator overload that applies a [merge]. */
839     @Stable operator fun plus(other: ParagraphStyle): TextStyle = this.merge(other)
840 
841     /** Plus operator overload that applies a [merge]. */
842     @Stable operator fun plus(other: SpanStyle): TextStyle = this.merge(other)
843 
844     @Deprecated(
845         "TextStyle copy constructors that do not take new stable parameters " +
846             "like LineHeightStyle, LineBreak, Hyphens are deprecated. Please use the new stable " +
847             "copy constructor.",
848         level = DeprecationLevel.HIDDEN
849     )
850     fun copy(
851         color: Color = this.spanStyle.color,
852         fontSize: TextUnit = this.spanStyle.fontSize,
853         fontWeight: FontWeight? = this.spanStyle.fontWeight,
854         fontStyle: FontStyle? = this.spanStyle.fontStyle,
855         fontSynthesis: FontSynthesis? = this.spanStyle.fontSynthesis,
856         fontFamily: FontFamily? = this.spanStyle.fontFamily,
857         fontFeatureSettings: String? = this.spanStyle.fontFeatureSettings,
858         letterSpacing: TextUnit = this.spanStyle.letterSpacing,
859         baselineShift: BaselineShift? = this.spanStyle.baselineShift,
860         textGeometricTransform: TextGeometricTransform? = this.spanStyle.textGeometricTransform,
861         localeList: LocaleList? = this.spanStyle.localeList,
862         background: Color = this.spanStyle.background,
863         textDecoration: TextDecoration? = this.spanStyle.textDecoration,
864         shadow: Shadow? = this.spanStyle.shadow,
865         textAlign: TextAlign? = this.paragraphStyle.textAlign,
866         textDirection: TextDirection? = this.paragraphStyle.textDirection,
867         lineHeight: TextUnit = this.paragraphStyle.lineHeight,
868         textIndent: TextIndent? = this.paragraphStyle.textIndent
869     ): TextStyle {
870         return TextStyle(
871             spanStyle =
872                 SpanStyle(
873                     textForegroundStyle =
874                         if (color == this.spanStyle.color) {
875                             spanStyle.textForegroundStyle
876                         } else {
877                             TextForegroundStyle.from(color)
878                         },
879                     fontSize = fontSize,
880                     fontWeight = fontWeight,
881                     fontStyle = fontStyle,
882                     fontSynthesis = fontSynthesis,
883                     fontFamily = fontFamily,
884                     fontFeatureSettings = fontFeatureSettings,
885                     letterSpacing = letterSpacing,
886                     baselineShift = baselineShift,
887                     textGeometricTransform = textGeometricTransform,
888                     localeList = localeList,
889                     background = background,
890                     textDecoration = textDecoration,
891                     shadow = shadow,
892                     platformStyle = this.spanStyle.platformStyle,
893                     drawStyle = this.spanStyle.drawStyle
894                 ),
895             paragraphStyle =
896                 ParagraphStyle(
897                     textAlign = textAlign ?: TextAlign.Unspecified,
898                     textDirection = textDirection ?: TextDirection.Unspecified,
899                     lineHeight = lineHeight,
900                     textIndent = textIndent,
901                     platformStyle = this.paragraphStyle.platformStyle,
902                     lineHeightStyle = this.lineHeightStyle,
903                     lineBreak = this.lineBreak,
904                     hyphens = this.hyphens,
905                     textMotion = this.textMotion
906                 ),
907             platformStyle = this.platformStyle
908         )
909     }
910 
911     @Deprecated(
912         "TextStyle copy constructors that do not take new stable parameters " +
913             "like LineHeightStyle, LineBreak, Hyphens are deprecated. Please use the new stable " +
914             "copy constructor.",
915         level = DeprecationLevel.HIDDEN
916     )
copynull917     fun copy(
918         color: Color = this.spanStyle.color,
919         fontSize: TextUnit = this.spanStyle.fontSize,
920         fontWeight: FontWeight? = this.spanStyle.fontWeight,
921         fontStyle: FontStyle? = this.spanStyle.fontStyle,
922         fontSynthesis: FontSynthesis? = this.spanStyle.fontSynthesis,
923         fontFamily: FontFamily? = this.spanStyle.fontFamily,
924         fontFeatureSettings: String? = this.spanStyle.fontFeatureSettings,
925         letterSpacing: TextUnit = this.spanStyle.letterSpacing,
926         baselineShift: BaselineShift? = this.spanStyle.baselineShift,
927         textGeometricTransform: TextGeometricTransform? = this.spanStyle.textGeometricTransform,
928         localeList: LocaleList? = this.spanStyle.localeList,
929         background: Color = this.spanStyle.background,
930         textDecoration: TextDecoration? = this.spanStyle.textDecoration,
931         shadow: Shadow? = this.spanStyle.shadow,
932         textAlign: TextAlign? = this.paragraphStyle.textAlign,
933         textDirection: TextDirection? = this.paragraphStyle.textDirection,
934         lineHeight: TextUnit = this.paragraphStyle.lineHeight,
935         textIndent: TextIndent? = this.paragraphStyle.textIndent,
936         platformStyle: PlatformTextStyle? = this.platformStyle,
937         lineHeightStyle: LineHeightStyle? = this.paragraphStyle.lineHeightStyle
938     ): TextStyle {
939         return TextStyle(
940             spanStyle =
941                 SpanStyle(
942                     textForegroundStyle =
943                         if (color == this.spanStyle.color) {
944                             spanStyle.textForegroundStyle
945                         } else {
946                             TextForegroundStyle.from(color)
947                         },
948                     fontSize = fontSize,
949                     fontWeight = fontWeight,
950                     fontStyle = fontStyle,
951                     fontSynthesis = fontSynthesis,
952                     fontFamily = fontFamily,
953                     fontFeatureSettings = fontFeatureSettings,
954                     letterSpacing = letterSpacing,
955                     baselineShift = baselineShift,
956                     textGeometricTransform = textGeometricTransform,
957                     localeList = localeList,
958                     background = background,
959                     textDecoration = textDecoration,
960                     shadow = shadow,
961                     platformStyle = platformStyle?.spanStyle,
962                     drawStyle = this.spanStyle.drawStyle
963                 ),
964             paragraphStyle =
965                 ParagraphStyle(
966                     textAlign = textAlign ?: TextAlign.Unspecified,
967                     textDirection = textDirection ?: TextDirection.Unspecified,
968                     lineHeight = lineHeight,
969                     textIndent = textIndent,
970                     platformStyle = platformStyle?.paragraphStyle,
971                     lineHeightStyle = lineHeightStyle,
972                     lineBreak = this.lineBreak,
973                     hyphens = this.hyphens,
974                     textMotion = this.textMotion
975                 ),
976             platformStyle = platformStyle
977         )
978     }
979 
980     @Deprecated(
981         "TextStyle copy constructors that do not take new stable parameters " +
982             "like LineBreak, Hyphens, and TextMotion are deprecated. Please use the new stable " +
983             "copy constructor.",
984         level = DeprecationLevel.HIDDEN
985     )
copynull986     fun copy(
987         color: Color = this.spanStyle.color,
988         fontSize: TextUnit = this.spanStyle.fontSize,
989         fontWeight: FontWeight? = this.spanStyle.fontWeight,
990         fontStyle: FontStyle? = this.spanStyle.fontStyle,
991         fontSynthesis: FontSynthesis? = this.spanStyle.fontSynthesis,
992         fontFamily: FontFamily? = this.spanStyle.fontFamily,
993         fontFeatureSettings: String? = this.spanStyle.fontFeatureSettings,
994         letterSpacing: TextUnit = this.spanStyle.letterSpacing,
995         baselineShift: BaselineShift? = this.spanStyle.baselineShift,
996         textGeometricTransform: TextGeometricTransform? = this.spanStyle.textGeometricTransform,
997         localeList: LocaleList? = this.spanStyle.localeList,
998         background: Color = this.spanStyle.background,
999         textDecoration: TextDecoration? = this.spanStyle.textDecoration,
1000         shadow: Shadow? = this.spanStyle.shadow,
1001         textAlign: TextAlign? = this.paragraphStyle.textAlign,
1002         textDirection: TextDirection? = this.paragraphStyle.textDirection,
1003         lineHeight: TextUnit = this.paragraphStyle.lineHeight,
1004         textIndent: TextIndent? = this.paragraphStyle.textIndent,
1005         platformStyle: PlatformTextStyle? = this.platformStyle,
1006         lineHeightStyle: LineHeightStyle? = this.paragraphStyle.lineHeightStyle,
1007         lineBreak: LineBreak? = this.paragraphStyle.lineBreak,
1008         hyphens: Hyphens? = this.paragraphStyle.hyphens
1009     ): TextStyle {
1010         return TextStyle(
1011             spanStyle =
1012                 SpanStyle(
1013                     textForegroundStyle =
1014                         if (color == this.spanStyle.color) {
1015                             spanStyle.textForegroundStyle
1016                         } else {
1017                             TextForegroundStyle.from(color)
1018                         },
1019                     fontSize = fontSize,
1020                     fontWeight = fontWeight,
1021                     fontStyle = fontStyle,
1022                     fontSynthesis = fontSynthesis,
1023                     fontFamily = fontFamily,
1024                     fontFeatureSettings = fontFeatureSettings,
1025                     letterSpacing = letterSpacing,
1026                     baselineShift = baselineShift,
1027                     textGeometricTransform = textGeometricTransform,
1028                     localeList = localeList,
1029                     background = background,
1030                     textDecoration = textDecoration,
1031                     shadow = shadow,
1032                     platformStyle = platformStyle?.spanStyle,
1033                     drawStyle = this.drawStyle
1034                 ),
1035             paragraphStyle =
1036                 ParagraphStyle(
1037                     textAlign = textAlign ?: TextAlign.Unspecified,
1038                     textDirection = textDirection ?: TextDirection.Unspecified,
1039                     lineHeight = lineHeight,
1040                     textIndent = textIndent,
1041                     platformStyle = platformStyle?.paragraphStyle,
1042                     lineHeightStyle = lineHeightStyle,
1043                     lineBreak = lineBreak ?: LineBreak.Unspecified,
1044                     hyphens = hyphens ?: Hyphens.Unspecified,
1045                     textMotion = this.textMotion
1046                 ),
1047             platformStyle = platformStyle
1048         )
1049     }
1050 
1051     @Deprecated(
1052         "copy constructors that take nullable TextAlign, " +
1053             "TextDirection, LineBreak, and Hyphens are deprecated. Please use a new constructor " +
1054             "where these parameters are non-nullable. Null value has been replaced by a special " +
1055             "Unspecified object for performance reason.",
1056         level = DeprecationLevel.HIDDEN
1057     )
copynull1058     fun copy(
1059         color: Color = this.spanStyle.color,
1060         fontSize: TextUnit = this.spanStyle.fontSize,
1061         fontWeight: FontWeight? = this.spanStyle.fontWeight,
1062         fontStyle: FontStyle? = this.spanStyle.fontStyle,
1063         fontSynthesis: FontSynthesis? = this.spanStyle.fontSynthesis,
1064         fontFamily: FontFamily? = this.spanStyle.fontFamily,
1065         fontFeatureSettings: String? = this.spanStyle.fontFeatureSettings,
1066         letterSpacing: TextUnit = this.spanStyle.letterSpacing,
1067         baselineShift: BaselineShift? = this.spanStyle.baselineShift,
1068         textGeometricTransform: TextGeometricTransform? = this.spanStyle.textGeometricTransform,
1069         localeList: LocaleList? = this.spanStyle.localeList,
1070         background: Color = this.spanStyle.background,
1071         textDecoration: TextDecoration? = this.spanStyle.textDecoration,
1072         shadow: Shadow? = this.spanStyle.shadow,
1073         drawStyle: DrawStyle? = this.spanStyle.drawStyle,
1074         textAlign: TextAlign? = this.paragraphStyle.textAlign,
1075         textDirection: TextDirection? = this.paragraphStyle.textDirection,
1076         lineHeight: TextUnit = this.paragraphStyle.lineHeight,
1077         textIndent: TextIndent? = this.paragraphStyle.textIndent,
1078         platformStyle: PlatformTextStyle? = this.platformStyle,
1079         lineHeightStyle: LineHeightStyle? = this.paragraphStyle.lineHeightStyle,
1080         lineBreak: LineBreak? = this.paragraphStyle.lineBreak,
1081         hyphens: Hyphens? = this.paragraphStyle.hyphens,
1082         textMotion: TextMotion? = this.paragraphStyle.textMotion,
1083     ): TextStyle {
1084         return TextStyle(
1085             spanStyle =
1086                 SpanStyle(
1087                     textForegroundStyle =
1088                         if (color == this.spanStyle.color) {
1089                             spanStyle.textForegroundStyle
1090                         } else {
1091                             TextForegroundStyle.from(color)
1092                         },
1093                     fontSize = fontSize,
1094                     fontWeight = fontWeight,
1095                     fontStyle = fontStyle,
1096                     fontSynthesis = fontSynthesis,
1097                     fontFamily = fontFamily,
1098                     fontFeatureSettings = fontFeatureSettings,
1099                     letterSpacing = letterSpacing,
1100                     baselineShift = baselineShift,
1101                     textGeometricTransform = textGeometricTransform,
1102                     localeList = localeList,
1103                     background = background,
1104                     textDecoration = textDecoration,
1105                     shadow = shadow,
1106                     platformStyle = platformStyle?.spanStyle,
1107                     drawStyle = drawStyle
1108                 ),
1109             paragraphStyle =
1110                 ParagraphStyle(
1111                     textAlign = textAlign ?: TextAlign.Unspecified,
1112                     textDirection = textDirection ?: TextDirection.Unspecified,
1113                     lineHeight = lineHeight,
1114                     textIndent = textIndent,
1115                     platformStyle = platformStyle?.paragraphStyle,
1116                     lineHeightStyle = lineHeightStyle,
1117                     lineBreak = lineBreak ?: LineBreak.Unspecified,
1118                     hyphens = hyphens ?: Hyphens.Unspecified,
1119                     textMotion = textMotion
1120                 ),
1121             platformStyle = platformStyle
1122         )
1123     }
1124 
copynull1125     fun copy(
1126         color: Color = this.spanStyle.color,
1127         fontSize: TextUnit = this.spanStyle.fontSize,
1128         fontWeight: FontWeight? = this.spanStyle.fontWeight,
1129         fontStyle: FontStyle? = this.spanStyle.fontStyle,
1130         fontSynthesis: FontSynthesis? = this.spanStyle.fontSynthesis,
1131         fontFamily: FontFamily? = this.spanStyle.fontFamily,
1132         fontFeatureSettings: String? = this.spanStyle.fontFeatureSettings,
1133         letterSpacing: TextUnit = this.spanStyle.letterSpacing,
1134         baselineShift: BaselineShift? = this.spanStyle.baselineShift,
1135         textGeometricTransform: TextGeometricTransform? = this.spanStyle.textGeometricTransform,
1136         localeList: LocaleList? = this.spanStyle.localeList,
1137         background: Color = this.spanStyle.background,
1138         textDecoration: TextDecoration? = this.spanStyle.textDecoration,
1139         shadow: Shadow? = this.spanStyle.shadow,
1140         drawStyle: DrawStyle? = this.spanStyle.drawStyle,
1141         textAlign: TextAlign = this.paragraphStyle.textAlign,
1142         textDirection: TextDirection = this.paragraphStyle.textDirection,
1143         lineHeight: TextUnit = this.paragraphStyle.lineHeight,
1144         textIndent: TextIndent? = this.paragraphStyle.textIndent,
1145         platformStyle: PlatformTextStyle? = this.platformStyle,
1146         lineHeightStyle: LineHeightStyle? = this.paragraphStyle.lineHeightStyle,
1147         lineBreak: LineBreak = this.paragraphStyle.lineBreak,
1148         hyphens: Hyphens = this.paragraphStyle.hyphens,
1149         textMotion: TextMotion? = this.paragraphStyle.textMotion,
1150     ): TextStyle {
1151         return TextStyle(
1152             spanStyle =
1153                 SpanStyle(
1154                     textForegroundStyle =
1155                         if (color == this.spanStyle.color) {
1156                             spanStyle.textForegroundStyle
1157                         } else {
1158                             TextForegroundStyle.from(color)
1159                         },
1160                     fontSize = fontSize,
1161                     fontWeight = fontWeight,
1162                     fontStyle = fontStyle,
1163                     fontSynthesis = fontSynthesis,
1164                     fontFamily = fontFamily,
1165                     fontFeatureSettings = fontFeatureSettings,
1166                     letterSpacing = letterSpacing,
1167                     baselineShift = baselineShift,
1168                     textGeometricTransform = textGeometricTransform,
1169                     localeList = localeList,
1170                     background = background,
1171                     textDecoration = textDecoration,
1172                     shadow = shadow,
1173                     platformStyle = platformStyle?.spanStyle,
1174                     drawStyle = drawStyle
1175                 ),
1176             paragraphStyle =
1177                 ParagraphStyle(
1178                     textAlign = textAlign,
1179                     textDirection = textDirection,
1180                     lineHeight = lineHeight,
1181                     textIndent = textIndent,
1182                     platformStyle = platformStyle?.paragraphStyle,
1183                     lineHeightStyle = lineHeightStyle,
1184                     lineBreak = lineBreak,
1185                     hyphens = hyphens,
1186                     textMotion = textMotion
1187                 ),
1188             platformStyle = platformStyle
1189         )
1190     }
1191 
1192     @Deprecated(
1193         "copy constructors that take nullable TextAlign, " +
1194             "TextDirection, LineBreak, and Hyphens are deprecated. Please use a new constructor " +
1195             "where these parameters are non-nullable. Null value has been replaced by a special " +
1196             "Unspecified object for performance reason.",
1197         level = DeprecationLevel.HIDDEN
1198     )
copynull1199     fun copy(
1200         brush: Brush?,
1201         alpha: Float = this.spanStyle.alpha,
1202         fontSize: TextUnit = this.spanStyle.fontSize,
1203         fontWeight: FontWeight? = this.spanStyle.fontWeight,
1204         fontStyle: FontStyle? = this.spanStyle.fontStyle,
1205         fontSynthesis: FontSynthesis? = this.spanStyle.fontSynthesis,
1206         fontFamily: FontFamily? = this.spanStyle.fontFamily,
1207         fontFeatureSettings: String? = this.spanStyle.fontFeatureSettings,
1208         letterSpacing: TextUnit = this.spanStyle.letterSpacing,
1209         baselineShift: BaselineShift? = this.spanStyle.baselineShift,
1210         textGeometricTransform: TextGeometricTransform? = this.spanStyle.textGeometricTransform,
1211         localeList: LocaleList? = this.spanStyle.localeList,
1212         background: Color = this.spanStyle.background,
1213         textDecoration: TextDecoration? = this.spanStyle.textDecoration,
1214         shadow: Shadow? = this.spanStyle.shadow,
1215         drawStyle: DrawStyle? = this.spanStyle.drawStyle,
1216         textAlign: TextAlign? = this.paragraphStyle.textAlign,
1217         textDirection: TextDirection? = this.paragraphStyle.textDirection,
1218         lineHeight: TextUnit = this.paragraphStyle.lineHeight,
1219         textIndent: TextIndent? = this.paragraphStyle.textIndent,
1220         platformStyle: PlatformTextStyle? = this.platformStyle,
1221         lineHeightStyle: LineHeightStyle? = this.paragraphStyle.lineHeightStyle,
1222         lineBreak: LineBreak? = this.paragraphStyle.lineBreak,
1223         hyphens: Hyphens? = this.paragraphStyle.hyphens,
1224         textMotion: TextMotion? = this.paragraphStyle.textMotion,
1225     ): TextStyle {
1226         return TextStyle(
1227             spanStyle =
1228                 SpanStyle(
1229                     brush = brush,
1230                     alpha = alpha,
1231                     fontSize = fontSize,
1232                     fontWeight = fontWeight,
1233                     fontStyle = fontStyle,
1234                     fontSynthesis = fontSynthesis,
1235                     fontFamily = fontFamily,
1236                     fontFeatureSettings = fontFeatureSettings,
1237                     letterSpacing = letterSpacing,
1238                     baselineShift = baselineShift,
1239                     textGeometricTransform = textGeometricTransform,
1240                     localeList = localeList,
1241                     background = background,
1242                     textDecoration = textDecoration,
1243                     shadow = shadow,
1244                     platformStyle = platformStyle?.spanStyle,
1245                     drawStyle = drawStyle
1246                 ),
1247             paragraphStyle =
1248                 ParagraphStyle(
1249                     textAlign = textAlign ?: TextAlign.Unspecified,
1250                     textDirection = textDirection ?: TextDirection.Unspecified,
1251                     lineHeight = lineHeight,
1252                     textIndent = textIndent,
1253                     platformStyle = platformStyle?.paragraphStyle,
1254                     lineHeightStyle = lineHeightStyle,
1255                     lineBreak = lineBreak ?: LineBreak.Unspecified,
1256                     hyphens = hyphens ?: Hyphens.Unspecified,
1257                     textMotion = textMotion
1258                 ),
1259             platformStyle = platformStyle
1260         )
1261     }
1262 
copynull1263     fun copy(
1264         brush: Brush?,
1265         alpha: Float = this.spanStyle.alpha,
1266         fontSize: TextUnit = this.spanStyle.fontSize,
1267         fontWeight: FontWeight? = this.spanStyle.fontWeight,
1268         fontStyle: FontStyle? = this.spanStyle.fontStyle,
1269         fontSynthesis: FontSynthesis? = this.spanStyle.fontSynthesis,
1270         fontFamily: FontFamily? = this.spanStyle.fontFamily,
1271         fontFeatureSettings: String? = this.spanStyle.fontFeatureSettings,
1272         letterSpacing: TextUnit = this.spanStyle.letterSpacing,
1273         baselineShift: BaselineShift? = this.spanStyle.baselineShift,
1274         textGeometricTransform: TextGeometricTransform? = this.spanStyle.textGeometricTransform,
1275         localeList: LocaleList? = this.spanStyle.localeList,
1276         background: Color = this.spanStyle.background,
1277         textDecoration: TextDecoration? = this.spanStyle.textDecoration,
1278         shadow: Shadow? = this.spanStyle.shadow,
1279         drawStyle: DrawStyle? = this.spanStyle.drawStyle,
1280         textAlign: TextAlign = this.paragraphStyle.textAlign,
1281         textDirection: TextDirection = this.paragraphStyle.textDirection,
1282         lineHeight: TextUnit = this.paragraphStyle.lineHeight,
1283         textIndent: TextIndent? = this.paragraphStyle.textIndent,
1284         platformStyle: PlatformTextStyle? = this.platformStyle,
1285         lineHeightStyle: LineHeightStyle? = this.paragraphStyle.lineHeightStyle,
1286         lineBreak: LineBreak = this.paragraphStyle.lineBreak,
1287         hyphens: Hyphens = this.paragraphStyle.hyphens,
1288         textMotion: TextMotion? = this.paragraphStyle.textMotion,
1289     ): TextStyle {
1290         return TextStyle(
1291             spanStyle =
1292                 SpanStyle(
1293                     brush = brush,
1294                     alpha = alpha,
1295                     fontSize = fontSize,
1296                     fontWeight = fontWeight,
1297                     fontStyle = fontStyle,
1298                     fontSynthesis = fontSynthesis,
1299                     fontFamily = fontFamily,
1300                     fontFeatureSettings = fontFeatureSettings,
1301                     letterSpacing = letterSpacing,
1302                     baselineShift = baselineShift,
1303                     textGeometricTransform = textGeometricTransform,
1304                     localeList = localeList,
1305                     background = background,
1306                     textDecoration = textDecoration,
1307                     shadow = shadow,
1308                     platformStyle = platformStyle?.spanStyle,
1309                     drawStyle = drawStyle
1310                 ),
1311             paragraphStyle =
1312                 ParagraphStyle(
1313                     textAlign = textAlign,
1314                     textDirection = textDirection,
1315                     lineHeight = lineHeight,
1316                     textIndent = textIndent,
1317                     platformStyle = platformStyle?.paragraphStyle,
1318                     lineHeightStyle = lineHeightStyle,
1319                     lineBreak = lineBreak,
1320                     hyphens = hyphens,
1321                     textMotion = textMotion
1322                 ),
1323             platformStyle = platformStyle
1324         )
1325     }
1326 
1327     /** The brush to use when drawing text. If not null, overrides [color]. */
1328     val brush: Brush?
1329         get() = this.spanStyle.brush
1330 
1331     /** The text color. */
1332     val color: Color
1333         get() = this.spanStyle.color
1334 
1335     /**
1336      * Opacity of text. This value is either provided along side Brush, or via alpha channel in
1337      * color.
1338      */
1339     val alpha: Float
1340         get() = this.spanStyle.alpha
1341 
1342     /**
1343      * The size of glyphs to use when painting the text. This may be [TextUnit.Unspecified] for
1344      * inheriting from another [TextStyle].
1345      */
1346     val fontSize: TextUnit
1347         get() = this.spanStyle.fontSize
1348 
1349     /** The typeface thickness to use when painting the text (e.g., bold). */
1350     val fontWeight: FontWeight?
1351         get() = this.spanStyle.fontWeight
1352 
1353     /** The typeface variant to use when drawing the letters (e.g., italic). */
1354     val fontStyle: FontStyle?
1355         get() = this.spanStyle.fontStyle
1356 
1357     /**
1358      * Whether to synthesize font weight and/or style when the requested weight or style cannot be
1359      * found in the provided font family.
1360      */
1361     val fontSynthesis: FontSynthesis?
1362         get() = this.spanStyle.fontSynthesis
1363 
1364     /** The font family to be used when rendering the text. */
1365     val fontFamily: FontFamily?
1366         get() = this.spanStyle.fontFamily
1367 
1368     /**
1369      * The advanced typography settings provided by font. The format is the same as the CSS
1370      * font-feature-settings attribute:
1371      * https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop
1372      */
1373     val fontFeatureSettings: String?
1374         get() = this.spanStyle.fontFeatureSettings
1375 
1376     /** The amount of space to add between each letter. */
1377     val letterSpacing: TextUnit
1378         get() = this.spanStyle.letterSpacing
1379 
1380     /** The amount by which the text is shifted up from the current baseline. */
1381     val baselineShift: BaselineShift?
1382         get() = this.spanStyle.baselineShift
1383 
1384     /** The geometric transformation applied the text. */
1385     val textGeometricTransform: TextGeometricTransform?
1386         get() = this.spanStyle.textGeometricTransform
1387 
1388     /** The locale list used to select region-specific glyphs. */
1389     val localeList: LocaleList?
1390         get() = this.spanStyle.localeList
1391 
1392     /** The background color for the text. */
1393     val background: Color
1394         get() = this.spanStyle.background
1395 
1396     /** The decorations to paint on the text (e.g., an underline). */
1397     val textDecoration: TextDecoration?
1398         get() = this.spanStyle.textDecoration
1399 
1400     /** The shadow effect applied on the text. */
1401     val shadow: Shadow?
1402         get() = this.spanStyle.shadow
1403 
1404     /** Drawing style of text, whether fill in the text while drawing or stroke around the edges. */
1405     val drawStyle: DrawStyle?
1406         get() = this.spanStyle.drawStyle
1407 
1408     /** The alignment of the text within the lines of the paragraph. */
1409     val textAlign: TextAlign
1410         get() = this.paragraphStyle.textAlign
1411 
1412     @Deprecated("Kept for backwards compatibility.", level = DeprecationLevel.WARNING)
1413     @get:JvmName("getTextAlign-buA522U") // b/320819734
1414     @Suppress("unused", "RedundantNullableReturnType", "PropertyName")
1415     val deprecated_boxing_textAlign: TextAlign?
1416         get() = this.textAlign
1417 
1418     /**
1419      * The algorithm to be used to resolve the final text and paragraph direction: Left To Right or
1420      * Right To Left. If no value is provided the system will use the [LayoutDirection] as the
1421      * primary signal.
1422      */
1423     val textDirection: TextDirection
1424         get() = this.paragraphStyle.textDirection
1425 
1426     @Deprecated("Kept for backwards compatibility.", level = DeprecationLevel.WARNING)
1427     @get:JvmName("getTextDirection-mmuk1to") // b/320819734
1428     @Suppress("unused", "RedundantNullableReturnType", "PropertyName")
1429     val deprecated_boxing_textDirection: TextDirection?
1430         get() = this.textDirection
1431 
1432     /** Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM. */
1433     val lineHeight: TextUnit
1434         get() = this.paragraphStyle.lineHeight
1435 
1436     /** The indentation of the paragraph. */
1437     val textIndent: TextIndent?
1438         get() = this.paragraphStyle.textIndent
1439 
1440     /**
1441      * The configuration for line height such as vertical alignment of the line, whether to apply
1442      * additional space as a result of line height to top of first line top and bottom of last line.
1443      *
1444      * The configuration is applied only when a [lineHeight] is defined.
1445      *
1446      * When null, [LineHeightStyle.Default] is used.
1447      */
1448     val lineHeightStyle: LineHeightStyle?
1449         get() = this.paragraphStyle.lineHeightStyle
1450 
1451     /** The hyphens configuration of the paragraph. */
1452     val hyphens: Hyphens
1453         get() = this.paragraphStyle.hyphens
1454 
1455     @Deprecated("Kept for backwards compatibility.", level = DeprecationLevel.WARNING)
1456     @get:JvmName("getHyphens-EaSxIns") // b/320819734
1457     @Suppress("unused", "RedundantNullableReturnType", "PropertyName")
1458     val deprecated_boxing_hyphens: Hyphens?
1459         get() = this.hyphens
1460 
1461     /** The line breaking configuration of the paragraph. */
1462     val lineBreak: LineBreak
1463         get() = this.paragraphStyle.lineBreak
1464 
1465     @Deprecated("Kept for backwards compatibility.", level = DeprecationLevel.WARNING)
1466     @get:JvmName("getLineBreak-LgCVezo") // b/320819734
1467     @Suppress("unused", "RedundantNullableReturnType", "PropertyName")
1468     val deprecated_boxing_lineBreak: LineBreak?
1469         get() = this.lineBreak
1470 
1471     /** Text character placement configuration, whether to optimize for animated or static text. */
1472     val textMotion: TextMotion?
1473         get() = this.paragraphStyle.textMotion
1474 
equalsnull1475     override fun equals(other: Any?): Boolean {
1476         if (this === other) return true
1477         if (other !is TextStyle) return false
1478 
1479         if (spanStyle != other.spanStyle) return false
1480         if (paragraphStyle != other.paragraphStyle) return false
1481         if (platformStyle != other.platformStyle) return false
1482 
1483         return true
1484     }
1485 
1486     /**
1487      * Returns true if text layout affecting attributes between this TextStyle and other are the
1488      * same.
1489      *
1490      * The attributes that do not require a layout change are color, textDecoration and shadow.
1491      *
1492      * Majority of attributes change text layout, and examples are line height, font properties,
1493      * font size, locale etc.
1494      *
1495      * This function can be used to identify if a new text layout is required for a given TextStyle.
1496      *
1497      * @param other The TextStyle to compare to.
1498      */
hasSameLayoutAffectingAttributesnull1499     fun hasSameLayoutAffectingAttributes(other: TextStyle): Boolean {
1500         return (this === other) ||
1501             (paragraphStyle == other.paragraphStyle &&
1502                 spanStyle.hasSameLayoutAffectingAttributes(other.spanStyle))
1503     }
1504 
hasSameDrawAffectingAttributesnull1505     fun hasSameDrawAffectingAttributes(other: TextStyle): Boolean {
1506         return (this === other) || (spanStyle.hasSameNonLayoutAttributes(other.spanStyle))
1507     }
1508 
hashCodenull1509     override fun hashCode(): Int {
1510         var result = spanStyle.hashCode()
1511         result = 31 * result + paragraphStyle.hashCode()
1512         result = 31 * result + (platformStyle?.hashCode() ?: 0)
1513         return result
1514     }
1515 
hashCodeLayoutAffectingAttributesnull1516     internal fun hashCodeLayoutAffectingAttributes(): Int {
1517         var result = spanStyle.hashCodeLayoutAffectingAttributes()
1518         result = 31 * result + paragraphStyle.hashCode()
1519         result = 31 * result + (platformStyle?.hashCode() ?: 0)
1520         return result
1521     }
1522 
toStringnull1523     override fun toString(): String {
1524         return "TextStyle(" +
1525             "color=$color, " +
1526             "brush=$brush, " +
1527             "alpha=$alpha, " +
1528             "fontSize=$fontSize, " +
1529             "fontWeight=$fontWeight, " +
1530             "fontStyle=$fontStyle, " +
1531             "fontSynthesis=$fontSynthesis, " +
1532             "fontFamily=$fontFamily, " +
1533             "fontFeatureSettings=$fontFeatureSettings, " +
1534             "letterSpacing=$letterSpacing, " +
1535             "baselineShift=$baselineShift, " +
1536             "textGeometricTransform=$textGeometricTransform, " +
1537             "localeList=$localeList, " +
1538             "background=$background, " +
1539             "textDecoration=$textDecoration, " +
1540             "shadow=$shadow, " +
1541             "drawStyle=$drawStyle, " +
1542             "textAlign=$textAlign, " +
1543             "textDirection=$textDirection, " +
1544             "lineHeight=$lineHeight, " +
1545             "textIndent=$textIndent, " +
1546             "platformStyle=$platformStyle, " +
1547             "lineHeightStyle=$lineHeightStyle, " +
1548             "lineBreak=$lineBreak, " +
1549             "hyphens=$hyphens, " +
1550             "textMotion=$textMotion" +
1551             ")"
1552     }
1553 
1554     companion object {
1555         /** Constant for default text style. */
1556         @Stable val Default = TextStyle()
1557     }
1558 }
1559 
1560 /**
1561  * Interpolate between two text styles.
1562  *
1563  * This will not work well if the styles don't set the same fields.
1564  *
1565  * The [fraction] argument represents position on the timeline, with 0.0 meaning that the
1566  * interpolation has not started, returning [start] (or something equivalent to [start]), 1.0
1567  * meaning that the interpolation has finished, returning [stop] (or something equivalent to
1568  * [stop]), and values in between meaning that the interpolation is at the relevant point on the
1569  * timeline between [start] and [stop]. The interpolation can be extrapolated beyond 0.0 and 1.0, so
1570  * negative values and values greater than 1.0 are valid.
1571  */
lerpnull1572 fun lerp(start: TextStyle, stop: TextStyle, fraction: Float): TextStyle {
1573     return TextStyle(
1574         spanStyle = lerp(start.toSpanStyle(), stop.toSpanStyle(), fraction),
1575         paragraphStyle = lerp(start.toParagraphStyle(), stop.toParagraphStyle(), fraction)
1576     )
1577 }
1578 
1579 /**
1580  * Fills missing values in TextStyle with default values and resolve [TextDirection].
1581  *
1582  * This function will fill all null or [TextUnit.Unspecified] field with actual values.
1583  *
1584  * @param style a text style to be resolved
1585  * @param direction a layout direction to be used for resolving text layout direction algorithm
1586  * @return resolved text style.
1587  */
resolveDefaultsnull1588 fun resolveDefaults(style: TextStyle, direction: LayoutDirection) =
1589     TextStyle(
1590         spanStyle = resolveSpanStyleDefaults(style.spanStyle),
1591         paragraphStyle = resolveParagraphStyleDefaults(style.paragraphStyle, direction),
1592         platformStyle = style.platformStyle
1593     )
1594 
1595 /** If [textDirection] is null returns a [TextDirection] based on [layoutDirection]. */
1596 internal fun resolveTextDirection(
1597     layoutDirection: LayoutDirection,
1598     textDirection: TextDirection
1599 ): TextDirection {
1600     return when (textDirection) {
1601         TextDirection.Content ->
1602             when (layoutDirection) {
1603                 LayoutDirection.Ltr -> TextDirection.ContentOrLtr
1604                 LayoutDirection.Rtl -> TextDirection.ContentOrRtl
1605             }
1606         TextDirection.Unspecified ->
1607             when (layoutDirection) {
1608                 LayoutDirection.Ltr -> TextDirection.Ltr
1609                 LayoutDirection.Rtl -> TextDirection.Rtl
1610             }
1611         else -> textDirection
1612     }
1613 }
1614 
createPlatformTextStyleInternalnull1615 private fun createPlatformTextStyleInternal(
1616     platformSpanStyle: PlatformSpanStyle?,
1617     platformParagraphStyle: PlatformParagraphStyle?
1618 ): PlatformTextStyle? {
1619     return if (platformSpanStyle == null && platformParagraphStyle == null) {
1620         null
1621     } else {
1622         createPlatformTextStyle(platformSpanStyle, platformParagraphStyle)
1623     }
1624 }
1625